StatefulWidget: apa itu, siklus hidup dan prinsip kerja

Penulis: IT Sectr Diterbitkan: 2026-07-01 Waktu membaca: 9 mnt

StatefulWidget — widget Flutter dengan status yang dapat diubah, memungkinkan UI merespons tindakan pengguna, peristiwa asinkron, dan aliran data. Menurut dokumentasi resmi Flutter (Flutter.dev, 2026), StatefulWidget digunakan untuk semua elemen interaktif aplikasi: formulir input, animasi, kotak centang, sakelar, dan layar yang memuat data dari jaringan. Berbeda dengan StatelessWidget, ia membuat objek State terpisah yang dipertahankan sepanjang siklus hidup dan dapat dibangun ulang tanpa membuat ulang widget itu sendiri.

Poin Utama

  • StatefulWidget — widget yang dapat mengubah statusnya selama bekerja, memicu pembangunan ulang UI melalui setState
  • Siklus hidup — StatefulWidget melalui tahapan createState, initState, didChangeDependencies, build, didUpdateWidget, dispose
  • Objek State — objek terpisah yang menyimpan status dan ada secara independen dari widget sepanjang masa hidupnya
  • setState — satu-satunya cara sah untuk memberi tahu Flutter tentang perlunya membangun ulang widget setelah perubahan data
  • Kinerja — penggunaan StatefulWidget yang berlebihan meningkatkan konsumsi memori dan waktu rendering

Apa itu StatefulWidget?

StatefulWidget — adalah kelas Flutter yang dapat mengubah statusnya sebagai respons terhadap tindakan pengguna, peristiwa sistem, atau operasi asinkron. Berbeda dengan StatelessWidget, StatefulWidget tidak ditampilkan secara langsung — ia membuat objek State yang bertanggung jawab untuk rendering. Pembagian menjadi dua kelas (Widget dan State) memungkinkan Flutter membangun ulang UI tanpa membuat ulang widget itu sendiri, yang memberikan keuntungan kinerja signifikan pada pembaruan yang sering.

Arsitektur StatefulWidget mengikuti pola «pemisahan yang dapat diubah dan tidak dapat diubah»: widget itu sendiri tetap tidak dapat diubah (seperti StatelessWidget), dan semua status yang dapat diubah disimpan dalam objek State terpisah. Ini memungkinkan Flutter menggunakan kembali widget dengan membandingkannya berdasarkan jenis dan Key, sambil mempertahankan status terkini di antara pembangunan ulang.

Menurut Google (Flutter Architectural Overview, 2026), StatefulWidget optimal untuk skenario di mana status berubah lebih dari sekali selama masa hidup widget: bidang teks, animasi, timer, aliran data, pemuatan asinkron. Untuk inisialisasi satu kali, StatelessWidget sudah cukup.

Kapan StatefulWidget Diperlukan

StatefulWidget wajib digunakan ketika widget harus merespons peristiwa eksternal: penekanan tombol, penyelesaian permintaan HTTP, pembaruan data dari database, langganan WebSocket. Juga diperlukan untuk widget dengan animasi, bidang teks dengan kontroler, dan komponen yang mengelola fokus. Jika widget hanya menampilkan data dan tidak menghasilkan peristiwa — gunakan StatelessWidget.

Struktur Internal

StatefulWidget terdiri dari dua kelas: StatefulWidget itu sendiri (ringan, tidak dapat diubah) dan State (berat, dapat diubah). Framework membuat State melalui metode createState(), yang dipanggil sekali saat ditempatkan di pohon. State mendapatkan referensi ke widget melalui properti widget dan dapat mengakses bidangnya kapan saja selama siklus hidup.

Siklus Hidup StatefulWidget

Siklus hidup StatefulWidget terdiri dari enam tahap utama, yang masing-masing menyediakan metode yang dapat ditimpa untuk melakukan tugas-tugas spesifik. Memahami tahapan ini sangat penting untuk bekerja dengan benar dengan sumber daya dan menghindari kebocoran memori.

createState

createState — metode pertama dari siklus hidup, dipanggil saat StatefulWidget ditempatkan di pohon. Harus mengembalikan instance baru State yang terkait dengan widget ini. Metode ini dipanggil tepat satu kali sepanjang masa hidup elemen. Penting untuk tidak melakukan operasi berat di sini — createState harus seringan mungkin.

initState

initState — dipanggil segera setelah pembuatan State, sebelum pembangunan UI pertama. Di sini dilakukan: inisialisasi kontroler (TextEditingController, AnimationController), langganan aliran data (StreamSubscription), pengaturan timer, dan inisialisasi awal bidang. Menurut dokumen Flutter (Flutter.dev, 2026), di initState tidak boleh memanggil BuildContext.of() — pohon belum sepenuhnya terpasang.

didChangeDependencies

didChangeDependencies — dipanggil setelah initState dan setiap kali dependensi InheritedWidget berubah. Ini adalah tempat yang tepat untuk memanggil MediaQuery.of(context) atau berlangganan Theme — nilai yang dapat berubah selama aplikasi berjalan. Jika widget menggunakan InheritedWidget, logika inisialisasi harus di sini, bukan di initState.

build dan didUpdateWidget

build — metode utama yang mengembalikan pohon widget. Dipanggil setelah initState, setelah didChangeDependencies, dan setelah setiap setState. didUpdateWidget dipanggil ketika induk membangun ulang dan mengirimkan StatefulWidget dengan parameter baru. Di sini Anda dapat membandingkan bidang widget lama dan baru dan, jika perlu, memperbarui status.

dispose

dispose — tahap akhir dari siklus hidup. Di sini semua sumber daya dibebaskan: berhenti berlangganan dari aliran, menghapus kontroler, membatalkan timer. Tidak memanggil dispose menyebabkan kebocoran memori. Setelah dispose, State dianggap mati — memanggil setState di dalamnya akan melempar pengecualian.

Bagaimana StatefulWidget Bekerja?

Mekanisme kerja StatefulWidget didasarkan pada kerja terkoordinasi dari tiga entitas: Widget (deskripsi ringan), Element (lapisan perantara), dan State (penyimpan data). Ketika Flutter menemukan StatefulWidget dalam deskripsi, ia membuat StatefulElement yang memanggil createState dan menyimpan referensi ke objek State. Saat induk membangun ulang, Flutter membandingkan widget baru dengan Element saat ini — jika jenis dan Key cocok, Element diperbarui dan State tetap sama.

Status hanya berubah melalui pemanggilan setState, yang memberi tahu framework tentang perlunya pembangunan ulang. Penting untuk dipahami: setState tidak mengubah status secara otomatis — ia hanya menandai widget sebagai «kotor». Pengembang memperbarui sendiri bidang State di callback yang diteruskan ke setState. Setelah callback selesai, Flutter memanggil build dan memperbarui UI.

Menurut tim Dart/Flutter (Dart Language Specification, 2026), pemisahan ini menjamin bahwa semua perubahan status terjadi secara sinkron sebelum pemanggilan build, menghilangkan situasi di mana UI menampilkan data yang diperbarui sebagian. Ini adalah mekanisme kunci konsistensi antarmuka di Flutter.

Contoh Kode dalam Dart

Mari kita lihat StatefulWidget sederhana — penghitung klik tombol. Ini menunjukkan pola dasar: pembuatan State, inisialisasi bidang di initState, perubahan melalui setState:

dart
class CounterScreen extends StatefulWidget {
  const CounterScreen({super.key});

  @override
  State<CounterScreen> createState() => _CounterScreenState();
}

class _CounterScreenState extends State<CounterScreen> {
  int _count = 0;

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

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('Jumlah: $_count'),
        ElevatedButton(
          onPressed: _increment,
          child: const Text('Tambah'),
        ),
      ],
    );
  }
}

Contoh dengan pemuatan data asinkron dan manajemen siklus hidup. StatefulWidget memuat data dari jaringan dan menampilkan status pemuatan:

dart
class UserProfilePage extends StatefulWidget {
  final String userId;
  const UserProfilePage({super.key, required this.userId});

  @override
  State<UserProfilePage> createState() => _UserProfilePageState();
}

class _UserProfilePageState extends State<UserProfilePage> {
  UserModel? _user;
  bool _isLoading = true;

  @override
  void initState() {
    super.initState();
    _loadUser();
  }

  Future<void> _loadUser() async {
    final user = await UserService.fetchUser(widget.userId);
    setState(() {
      _user = user;
      _isLoading = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    if (_isLoading) return const CircularProgressIndicator();
    return Text('Halo, ${_user!.name}');
  }
}

Dalam contoh kedua, penting untuk dicatat: initState memulai operasi asinkron, tetapi metode itu sendiri tidak asinkron. Asinkronitas direalisasikan melalui async/await di dalam metode terpisah _loadUser, yang memperbarui status melalui setState setelah permintaan selesai. Pendekatan ini menjamin bahwa widget akan menampilkan indikator pemuatan dengan benar sebelum menerima data.

StatefulWidget vs StatelessWidget

Pilihan antara StatefulWidget dan StatelessWidget bukan hanya soal keberadaan status. StatefulWidget menyediakan siklus hidup lengkap dengan metode initState, didChangeDependencies, didUpdateWidget, dan dispose, yang diperlukan untuk bekerja dengan kontroler, animasi, dan aliran. StatelessWidget, pada gilirannya, tidak memiliki metode ini dan selalu lebih ringan untuk framework.

Rekomendasi tim Flutter (Flutter docs, 2026) — minimalkan jumlah StatefulWidget dalam aplikasi, dengan mengangkat status ke atas pohon (State Hoisting) atau menggunakan solusi manajemen status (Riverpod, Bloc, Provider). Setiap StatefulWidget membuat objek State yang hidup sampai elemen dihapus — semakin banyak widget seperti itu, semakin tinggi beban memori.

KriteriaStatefulWidgetStatelessWidget
StatusDapat diubahTidak dapat diubah
Siklus hidup6 tahapHanya build
Objek StateDibuat terpisahTidak diperlukan
setStateTersediaTidak tersedia
LanggananinitState/disposeTidak didukung
Konstruktor constTerbatasSepenuhnya didukung
Konsumsi memoriLebih tinggiLebih rendah

Kinerja dan Optimasi

StatefulWidget membutuhkan lebih banyak sumber daya daripada StatelessWidget karena kebutuhan untuk membuat dan memelihara objek State. Namun, penggunaan StatefulWidget yang benar tidak menyebabkan masalah kinerja jika beberapa aturan dipatuhi. Pertama, hindari penyarangan StatefulWidget yang dalam — setiap level menambah overhead untuk traversal pohon. Kedua, bagi StatefulWidget kompleks menjadi beberapa widget sederhana, yang masing-masing bertanggung jawab atas bagian statusnya sendiri.

Menurut penelitian Flutter Performance (Flutter.dev, Februari 2026), penyebab paling umum penurunan FPS adalah pemanggilan setState di widget induk yang membangun ulang semua turunan, termasuk StatelessWidget yang tidak mengubah tampilannya. Solusinya — pindahkan bagian UI yang dapat diubah ke StatefulWidget terpisah, sehingga setState hanya membangun ulang widget minimum yang diperlukan.

Penggunaan const di dalam State adalah teknik penting lainnya. Jika widget anak dinyatakan sebagai const, Flutter tidak akan membangunnya ulang saat setState dipanggil di induk. Ini mengurangi beban framework dan memperpendek waktu rendering frame.

Hindari setState yang Sering

Setiap pemanggilan setState memicu pembangunan ulang penuh widget. Jika status berubah dengan frekuensi tinggi (misalnya, animasi atau aliran data), pertimbangkan penggunaan AnimatedBuilder, ValueListenableBuilder, atau StreamBuilder daripada pemanggilan setState manual. Widget ini mengoptimalkan pembangunan ulang, hanya memperbarui bagian UI yang benar-benar berubah.

Kesalahan Umum

Kesalahan umum pertama dengan StatefulWidget — memanggil setState setelah dispose. Ketika widget dihapus dari pohon, State dianggap mati dan setiap panggilan setState melempar pengecualian «setState called after dispose». Paling sering ini terjadi ketika operasi asinkron selesai setelah widget dihapus. Solusinya — periksa bendera mounted sebelum memanggil setState atau batalkan operasi asinkron di dispose.

Kesalahan kedua — melakukan perhitungan berat di metode build. Karena build dipanggil pada setiap setState dan setiap pembangunan ulang induk, semua perhitungan harus seringan mungkin. Jika perlu melakukan operasi intensif sumber daya — pindahkan ke Isolate terpisah atau simpan hasilnya di bidang State.

Kesalahan ketiga — tidak memanggil super.initState() dan super.dispose(). Saat menimpa metode ini, pengembang wajib memanggil implementasi induk. Jika tidak dilakukan, framework tidak dapat mengelola status Element dengan benar, yang mengarah ke bug yang sulit dilacak.

Rekomendasi untuk Menghindari Kesalahan

  • Selalu periksa mounted sebelum setState di callback asinkron
  • Jangan lupa memanggil super.initState() dan super.dispose()
  • Jangan melakukan permintaan HTTP langsung di build — gunakan initState
  • Berhenti berlangganan dari semua langganan di dispose
  • Gunakan jumlah StatefulWidget minimum dalam proyek

Pertanyaan yang Sering Diajukan

Apa perbedaan StatefulWidget dengan StatelessWidget?

StatefulWidget dapat mengubah statusnya melalui setState, memiliki siklus hidup (initState, dispose) dan membuat objek State terpisah. StatelessWidget tidak dapat mengubah status dan tidak memiliki metode siklus hidup — ia hanya menampilkan data yang diberikan.

Berapa kali createState dipanggil?

createState dipanggil tepat satu kali untuk setiap instance StatefulElement. Bahkan jika induk membangun ulang berkali-kali, selama jenis dan Key widget tidak berubah, createState tidak dipanggil — objek State yang ada digunakan.

Apa yang terjadi jika dispose tidak dipanggil?

Sumber daya tidak akan dibebaskan: kontroler akan terus bekerja di latar belakang, langganan aliran akan tetap aktif, timer tidak akan dibatalkan. Ini menyebabkan kebocoran memori dan dapat memicu pemanggilan setState setelah dispose, yang melempar pengecualian.

Bisakah StatefulWidget menjadi const?

Ya, konstruktor StatefulWidget bisa const. Namun, ini tidak memberikan keuntungan yang sama seperti untuk StatelessWidget — objek State akan tetap dibuat saat penempatan pertama. const hanya memengaruhi widget itu sendiri (pembungkus ringan), bukan State.

Untuk apa metode didUpdateWidget?

didUpdateWidget dipanggil ketika induk mengirimkan StatefulWidget dengan parameter baru. Ini diperlukan untuk menyinkronkan status dengan data baru — misalnya, jika userId berubah di parameter, profil pengguna baru perlu dimuat.

Ringkasan

  • StatefulWidget — widget dengan status yang dapat diubah yang menggunakan objek State terpisah untuk penyimpanan data dan manajemen siklus hidup
  • Siklus hidup terdiri dari createState, initState, didChangeDependencies, build, didUpdateWidget, dan dispose, masing-masing dengan tujuannya sendiri
  • setState — satu-satunya cara sah untuk memberi tahu framework tentang perubahan status, setelah itu build dipanggil secara otomatis
  • mounted — bendera yang harus diperiksa sebelum setState dalam operasi asinkron untuk menghindari pengecualian setelah dispose
  • Kinerja — StatefulWidget membutuhkan lebih banyak sumber daya daripada StatelessWidget; disarankan untuk meminimalkan jumlahnya dengan memindahkan status ke lapisan eksternal
  • Widget anak const di dalam State memungkinkan mengurangi volume pembangunan ulang saat setState dipanggil, meningkatkan kinerja
  • Pilihan yang tepat — gunakan StatefulWidget hanya ketika widget perlu mengelola data yang dapat diubah atau operasi asinkron

Kami akan mengembangkan aplikasi seluler turnkey

IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.

Diskusikan proyek

Baca juga