MOBILE DEVELOPMENT • FLUTTER

STATE
MANAGEMENT

BAB 4 — Fundamental Pengelolaan State pada Aplikasi Flutter. Memahami bagaimana data hidup, mengalir, dan diperbarui di dalam aplikasi.

Kelas 11 • Semester 2 SMK IT — RPL 22+ Slide Interaktif

Gunakan tombol ◀ ▶ atau panah keyboard untuk navigasi

BAB 4 • STATE MANAGEMENT

Agenda & Peta Belajar

Di bab ini kamu akan belajar bagaimana aplikasi Flutter mengingat dan memperbarui data. Ikuti urutannya dari yang paling dasar sampai perbandingan teknik profesional.

1
Apa itu State?Konsep dasar + analogi lampu
2
Widget TreeStruktur pohon widget di Flutter
3
Data FlowAliran data dari atas ke bawah
4
Rebuild & Re-renderBagaimana UI diperbarui
5
setStateCara paling dasar mengelola state
6
InheritedWidgetBerbagi data tanpa prop drilling
7
Provider, BLoC, RiverpodState management modern
8
Perbandingan & LatihanKapan pakai apa + tugas akhir
BAB 4 • STATE MANAGEMENT

Apa itu State?

📌 Definisi State

State adalah data yang bisa berubah selama aplikasi berjalan, dan ketika data itu berubah, tampilan (UI) ikut berubah. Contoh: jumlah like, status login, isi keranjang belanja, atau mode gelap/terang.

🎯 Analogi: Saklar Lampu

state = false

Lampu punya state: nyala atau mati. Saat kamu menekan saklar, state berubah dan kondisi lampu (UI) ikut berubah. Di Flutter, mengubah state = memerintahkan UI menggambar ulang dirinya.

🔑 Dua Jenis State

  • Ephemeral / Local State — state milik satu widget saja (contoh: animasi, tab aktif). Cukup pakai setState.
  • App / Shared State — state yang dibagi banyak widget (contoh: data user login, keranjang). Butuh Provider/Bloc/Riverpod.
Dart / Flutter
bool isLampOn = false; // ini adalah STATE

void toggleLamp() {
  setState(() {
    isLampOn = !isLampOn; // ubah state -> UI digambar ulang
  });
}
BAB 4 • STATE MANAGEMENT

State dalam Flutter

📌 StatelessWidget vs StatefulWidget

  • StatelessWidget — tidak punya state yang berubah. Sekali digambar, tetap. Contoh: ikon, teks statis.
  • StatefulWidget — punya objek State yang menyimpan data berubah dan bisa memanggil setState().
Dart / Flutter
class Lampu extends StatefulWidget {
  @override
  State<Lampu> createState() => _LampuState();
}

class _LampuState extends State<Lampu> {
  bool isOn = false; // STATE disimpan di sini

  @override
  Widget build(BuildContext context) {
    return Switch(
      value: isOn,
      onChanged: (v) => setState(() => isOn = v),
    );
  }
}

▶ Demo Live State

🌙
isOn = false
build() dipanggil: 1×

Tiap klik memanggil setState(), Flutter menjalankan ulang build() sehingga UI sinkron dengan state terbaru.

BAB 4 • STATE MANAGEMENT

Widget Tree

📌 Semua adalah Widget

Di Flutter, UI tersusun sebagai pohon widget (widget tree). Widget induk membungkus widget anak, membentuk hierarki dari atas (root) ke bawah (daun).

🌳 Flowchart Animasi: Widget Tree

MaterialApp
Scaffold
AppBar
Body → Column
Text
SizedBox
ElevatedButton

Seperti silsilah keluarga: setiap widget punya induk dan bisa punya banyak anak. Posisi di pohon menentukan dari mana sebuah widget bisa mengambil data.

BAB 4 • STATE MANAGEMENT

Membaca Widget Tree

📌 Indentasi = Kedalaman Pohon

Setiap level menjorok ke dalam menandakan anak dari widget di atasnya. BuildContext adalah "alamat" posisi widget di dalam pohon ini.

Dart / Flutter
MaterialApp(                    // root
  home: Scaffold(               // level 1
    appBar: AppBar(             // level 2
      title: Text('Halo'),      // level 3
    ),
    body: Column(               // level 2
      children: [
        Text('Counter:'),       // level 3
        SizedBox(height: 8),    // level 3
        ElevatedButton(         // level 3
          onPressed: () {},
          child: Text('Tambah'),
        ),
      ],
    ),
  ),
)

💡 Aturan penting: data hanya bisa mengalir dari induk ke anak. Anak tidak bisa langsung "naik" mengambil data dari induknya kecuali lewat mekanisme khusus seperti InheritedWidget / Provider.

BAB 4 • STATE MANAGEMENT

Data Flow

📌 Data Mengalir ke Bawah

Di Flutter, data dikirim dari induk ke anak melalui parameter constructor. Ini disebut unidirectional data flow (aliran satu arah) — membuat aplikasi mudah dilacak dan diprediksi.

💧 Analogi: Air Terjun Bertingkat

Parent Widget
Child Widget
Grandchild Widget

Seperti air terjun: air (data) mengalir dari kolam paling atas ke bawah, tidak pernah naik ke atas dengan sendirinya. Klik tombol untuk mengalirkan data.

BAB 4 • STATE MANAGEMENT

Rebuild & Re-render

📌 Apa itu Rebuild?

Rebuild adalah proses Flutter menjalankan ulang method build() untuk menggambar UI sesuai state terbaru. Memanggil setState() memicu rebuild pada widget tersebut dan anak-anaknya.

🧱 Demo: Efek Rebuild

Rebuild ke-0

setState() → build() → Render ulang widget! Setiap blok di-render ulang. Karena itu, taruh setState sedekat mungkin dengan widget yang benar-benar berubah agar tidak boros.

BAB 4 • STATE MANAGEMENT

setState — Konsep

📌 Cara Kerja setState

setState() berkata kepada Flutter: "Datanya berubah, tolong gambar ulang!". Kamu mengubah variabel di dalam callback setState, lalu Flutter menjadwalkan rebuild.

🔔 Analogi: Bel Pelayan Restoran

🔔
Tekan bel untuk memanggil dapur...

Mengubah variabel saja seperti menulis pesanan tapi tidak membunyikan bel — dapur (Flutter) tidak tahu. setState() adalah bel yang memberi tahu Flutter untuk memproses ulang.

⚠️ Kesalahan Umum

  • Mengubah variabel tanpa setState → UI tidak berubah.
  • Memanggil setState di luar class State → error.
  • Logika berat di dalam setState → sebaiknya hitung dulu, baru setState ringan.
BAB 4 • STATE MANAGEMENT

setState — Live Demo

▶ Counter App (Berfungsi!)

0
Mulai dari nol!
Dart / Flutter
class _CounterState extends State<Counter> {
  int _count = 0;

  void _increment() {
    setState(() {
      _count++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('$_count', style: TextStyle(fontSize: 48)),
            ElevatedButton(
              onPressed: _increment,
              child: Text('Tambah'),
            ),
          ],
        ),
      ),
    );
  }
}
BAB 4 • STATE MANAGEMENT

InheritedWidget — Konsep

📌 Berbagi Data ke Bawah Secara Efisien

InheritedWidget menyimpan data di atas pohon, lalu semua keturunannya bisa mengaksesnya langsung tanpa mengoper data lewat setiap constructor (menghindari prop drilling).

👨‍👩‍👧‍👦 Analogi: Warisan Keluarga

👴 Kakek-Nenek (pemegang TEMA)
👨 Ayah-Ibu
🧑 Anak
👶 Cucu (butuh TEMA)

Kakek memegang "warna tema". Tanpa harus dititip lewat ayah lalu anak, cucu bisa langsung mengakses warisan kakek. Klik untuk melihat tiap generasi mengakses data.

BAB 4 • STATE MANAGEMENT

InheritedWidget — Code

Dart / Flutter
class ThemeData extends InheritedWidget {
  final Color primaryColor;

  const ThemeData({
    Key? key,
    required this.primaryColor,
    required Widget child,
  }) : super(key: key, child: child);

  // Cara cucu mengakses data kakek:
  static ThemeData of(BuildContext context) {
    return context
        .dependOnInheritedWidgetOfExactType<ThemeData>()!;
  }

  @override
  bool updateShouldNotify(ThemeData oldWidget) {
    return primaryColor != oldWidget.primaryColor;
  }
}

🔑 context.dependOnInheritedWidgetOfExactType<ThemeData>() = cara widget mana pun di bawah pohon "mendaftar" untuk mendapat data, dan otomatis di-rebuild saat data berubah (jika updateShouldNotify bernilai true).

📌 Kenapa Ini Penting?

InheritedWidget adalah fondasi dari hampir semua state management modern. Provider, misalnya, dibangun di atas InheritedWidget agar lebih mudah digunakan.

BAB 4 • STATE MANAGEMENT

Provider — Introduction

📌 Provider = InheritedWidget yang Mudah

Provider membungkus InheritedWidget agar lebih ringkas. Sebuah ChangeNotifier menyimpan data; saat data berubah, ia memanggil notifyListeners() dan semua Consumer otomatis rebuild.

🏪 Analogi: Toko & Pelanggan

TOKO
(Provider)
🧑
👩
🧒
👴

Toko (Provider) mengumumkan stok baru lewat notifyListeners(). Semua pelanggan (Consumer) yang berlangganan langsung tahu dan memperbarui diri. Klik untuk update.

BAB 4 • STATE MANAGEMENT

Provider — Code + Demo

Dart / Flutter
// ChangeNotifier
class ThemeProvider extends ChangeNotifier {
  bool _isDark = false;
  bool get isDark => _isDark;

  void toggleTheme() {
    _isDark = !_isDark;
    notifyListeners(); // beri tahu semua Consumer
  }
}

// Setup di main
ChangeNotifierProvider(
  create: (_) => ThemeProvider(),
  child: MaterialApp(home: MyHomePage()),
)

// Konsumsi di widget
Consumer<ThemeProvider>(
  builder: (context, theme, child) {
    return Container(
      color: theme.isDark ? Colors.black : Colors.white,
    );
  },
)

▶ Demo: Theme Switcher

🏠 Header
📝 Konten
⚙️ Footer

3 widget berlangganan ke ThemeProvider. Satu klik mengubah semuanya serentak — tanpa setState di tiap widget.

BAB 4 • STATE MANAGEMENT

BLoC — Konsep

📌 BLoC = Business Logic Component

BLoC memisahkan logika dari UI menggunakan aliran: EVENT masuk → diproses BLoC → menghasilkan STATE baru. Cocok untuk aplikasi besar yang butuh struktur rapi dan mudah dites.

🏭 Analogi: Mesin Pabrik

EVENT
Increment
BLoC
Proses
STATE
count: 1

Seperti pabrik: bahan mentah (Event) masuk ke mesin (BLoC), diolah, lalu keluar produk jadi (State). UI hanya menampilkan produk akhir. Klik untuk menjalankan mesin.

BAB 4 • STATE MANAGEMENT

BLoC — Code Pattern

Dart / Flutter
// Event
abstract class CounterEvent {}
class IncrementEvent extends CounterEvent {}

// State
class CounterState {
  final int count;
  CounterState(this.count);
}

// BLoC
class CounterBloc extends Bloc<CounterEvent, CounterState> {
  CounterBloc() : super(CounterState(0)) {
    on<IncrementEvent>((event, emit) {
      emit(CounterState(state.count + 1));
    });
  }
}

📌 Alur Penggunaan

  • UI mengirim event: context.read<CounterBloc>().add(IncrementEvent())
  • BLoC memproses lalu emit state baru.
  • BlocBuilder menampilkan state terbaru di layar.
BAB 4 • STATE MANAGEMENT

Riverpod — Konsep

📌 Riverpod = Provider versi Upgrade

Riverpod menyempurnakan Provider: tidak butuh BuildContext untuk mengakses data, lebih aman secara tipe (type-safe), dan mudah dites. Widget memakai ref.watch() untuk "menonton" sebuah provider.

🛰️ Analogi: Satelit & Penerima

PROVIDER
📱
💻
📺

Satu satelit (provider) menyiarkan data; semua penerima (consumer) yang menonton (ref.watch) langsung update saat siaran berubah. Klik untuk menyiarkan.

BAB 4 • STATE MANAGEMENT

Riverpod — Code

Dart / Flutter
// Definisi provider
final counterProvider =
    StateNotifierProvider<CounterNotifier, int>(
  (ref) => CounterNotifier(),
);

class CounterNotifier extends StateNotifier<int> {
  CounterNotifier() : super(0);

  void increment() => state++;
  void decrement() => state--;
}

// Konsumsi
class CounterWidget extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final count = ref.watch(counterProvider);
    return Text('$count');
  }
}

🔑 ref.watch(counterProvider) = menonton provider, widget otomatis rebuild saat nilainya berubah. ref.read(...) dipakai saat hanya ingin membaca/memanggil method tanpa menonton.

BAB 4 • STATE MANAGEMENT

Perbandingan 4 Framework

Tidak ada yang "paling benar" — pilih sesuai kebutuhan proyek.

KriteriasetStateProviderBLoCRiverpod
Kemudahan Pakai★★★★★★★★★☆★★☆☆☆★★★★☆
Skalabilitas★☆☆☆☆★★★☆☆★★★★★★★★★★
BoilerplateSedikitSedangBanyakSedang
Testing★★☆☆☆★★★☆☆★★★★★★★★★★
Popularitas★★★☆☆★★★★★★★★★☆★★★★☆

📊 Popularitas di Komunitas Flutter

setState
60%
Provider
92%
BLoC
78%
Riverpod
84%
BAB 4 • STATE MANAGEMENT

Kapan Pakai Framework Apa?

📌 Pohon Keputusan

Gunakan diagram ini sebagai panduan cepat memilih teknik state management sesuai skala dan kebutuhan aplikasimu.

🧭 Decision Flowchart

State hanya dipakai 1 widget?
✅ Ya → setState (paling sederhana)
State dibagi beberapa widget, proyek kecil-menengah?
✅ Ya → Provider atau Riverpod
Proyek besar, banyak logika & butuh testing ketat?
✅ Ya → BLoC (terstruktur & teruji)
📝 LATIHAN 1

setState Counter App

📋 Konteks Soal

Buat aplikasi counter sederhana dengan Flutter menggunakan setState. Aplikasi menampilkan angka dan bisa ditambah/dikurangi serta direset.

✅ Yang Harus Kamu Buat

  • Tampilkan angka counter yang mulai dari 0.
  • Tombol [+] untuk menambah dan [−] untuk mengurangi (tidak boleh negatif).
  • Tombol [Reset] untuk mereset kembali ke 0.
  • Tampilkan pesan berbeda berdasarkan nilai counter:
    • 0 → "Mulai dari nol!"   • 1–10 → "Bagus, terus tambah!"   • >10 → "Luar biasa!"

🏆 Kriteria Penilaian

KriteriaPoin
Counter tambah/kurang berfungsi & tidak negatif30
Tombol reset berfungsi dengan benar40
Pesan dinamis sesuai nilai counter30

Total: 100 poin

💡 Petunjuk

Gunakan satu variabel int _count = 0; di dalam class State. Bungkus setiap perubahan di dalam setState(() {...}). Untuk mencegah negatif, cek if (_count > 0) _count--;.

📝 LATIHAN 2

Provider Theme Switcher

📋 Konteks Soal

Buat aplikasi Flutter dengan tema dark/light yang menggunakan Provider. Saat tema diganti, beberapa widget berubah bersamaan.

✅ Yang Harus Kamu Buat

  • Setup ThemeProvider sebagai ChangeNotifier.
  • Toggle dark/light mode lewat Provider (notifyListeners()).
  • Minimal 3 widget yang ikut berubah saat tema berubah.
  • State tema tetap tersimpan (tidak reset saat widget rebuild).

🏆 Kriteria Penilaian

KriteriaPoin
ThemeProvider (ChangeNotifier) benar30
Toggle tema berfungsi via Provider40
Minimal 3 widget berubah serentak30

Total: 100 poin

💡 Petunjuk

Bungkus aplikasi dengan ChangeNotifierProvider di atas MaterialApp. Gunakan Consumer<ThemeProvider> atau context.watch<ThemeProvider>() pada widget yang perlu ikut berubah.

🎓 TUGAS AKHIR

Tugas Akhir BAB 4

📋 Konteks Soal

Implementasikan state management untuk sebuah aplikasi mini pilihanmu sendiri (misal: to-do list, catatan, kuis, atau keranjang belanja sederhana).

✅ Yang Harus Kamu Buat

  • Pilih SALAH SATU: setState, Provider, atau Riverpod.
  • Buat minimal 3 halaman/screen yang berbeda.
  • State harus bisa dibagi antar minimal 2 screen.
  • Sertakan komentar penjelasan di setiap bagian state management.

🏆 Kriteria Penilaian

KriteriaPoin
Ketepatan implementasi state management40
Kreativitas fitur aplikasi30
Kualitas kode (bersih & terdokumentasi)20
Presentasi & penjelasan10

Total: 100 poin

💡 Petunjuk

Mulai dari yang sederhana: rancang dulu data apa yang menjadi state, lalu tentukan screen mana yang membaca/mengubahnya. Gunakan navigasi Navigator.push antar screen, dan letakkan state di atas agar bisa dibagikan.

1 / 23