InheritedWidget — apa itu, transmisi data di pohon dan cara kerjanya

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

InheritedWidget — adalah widget khusus di Flutter yang mengirimkan data ke bawah pohon widget tanpa pengiriman eksplisit melalui konstruktor. Widget anak mendapatkan akses ke data melalui BuildContext dan secara otomatis berlangganan pembaruan. Ketika data di InheritedWidget berubah, semua widget yang bergantung akan dibangun ulang. Menurut Flutter API Reference, 2025, InheritedWidget mendasari Theme, MediaQuery, Localizations, dan sebagian besar pustaka manajemen status.

Poin Utama

  • InheritedWidget mengirimkan data ke bawah Widget Tree tanpa pengiriman eksplisit melalui setiap widget.
  • Langganan otomatis — widget yang menggunakan dependOnInheritedWidgetOfExactType akan dibangun ulang saat data berubah.
  • Theme dan MediaQuery — contoh bawaan InheritedWidget yang tersedia di setiap aplikasi Flutter.
  • Provider dan Riverpod dibangun di atas InheritedWidget dan memperluas kemampuannya dalam manajemen status.
  • Implementasi yang benar memerlukan override updateShouldNotify untuk mencegah pembangunan ulang yang tidak perlu.

Apa itu InheritedWidget di Flutter?

InheritedWidget — adalah widget yang membuat datanya dapat diakses oleh semua turunan di Widget Tree. Berbeda dengan widget biasa yang hanya mengirimkan data melalui konstruktor ke elemen anak, InheritedWidget memungkinkan widget mana pun di subpohon untuk mengakses data tanpa rantai parameter. Ini memecahkan masalah "prop drilling" — pengiriman data melalui banyak widget perantara yang sendiri tidak menggunakan data tersebut.

InheritedWidget bawaan

Flutter menyertakan beberapa InheritedWidget bawaan: Theme (skema warna dan gaya), MediaQuery (ukuran layar, orientasi, kerapatan piksel), Localizations (string yang dilokalisasi), Directionality (arah teks), DefaultTextStyle (gaya teks default). Widget ini diatur oleh widget root seperti MaterialApp dan tersedia di seluruh aplikasi.

Siklus hidup InheritedWidget

InheritedWidget tidak memiliki status sendiri — ia menyimpan data yang dikirimkan melalui konstruktor. Ketika induk InheritedWidget dibangun ulang dengan data baru, metode updateShouldNotify dipanggil untuk membandingkan data lama dan baru. Jika metode mengembalikan true, semua widget yang bergantung ditandai untuk dibangun ulang. Ini adalah mekanisme pembaruan reaktif yang sederhana namun efektif.

Bagaimana cara kerja transmisi data melalui InheritedWidget

Mekanisme transmisi data melalui InheritedWidget didasarkan pada Element Tree. Ketika widget memanggil dependOnInheritedWidgetOfExactType, elemen yang sesuai mendaftarkan ketergantungan pada InheritedElement. Saat InheritedWidget berubah, InheritedElement memberi tahu semua elemen yang bergantung, yang akan dibangun ulang di frame berikutnya.

Mendaftarkan ketergantungan

Metode dependOnInheritedWidgetOfExactType tidak hanya menemukan InheritedWidget di pohon — ia juga melanggankan elemen saat ini pada pemberitahuan. Jika Anda menggunakan findAncestorWidgetOfExactType alih-alih dependOn, widget akan menerima data tetapi tidak akan dibangun ulang saat data berubah. Ini adalah perbedaan penting: dependOn adalah langganan, findAncestor adalah pencarian satu kali.

Menelusuri pohon InheritedWidget

Ketika widget meminta InheritedWidget, Flutter naik melalui Element Tree dari elemen saat ini ke akar, memeriksa setiap InheritedElement untuk kecocokan tipe. InheritedElement pertama yang ditemukan dikembalikan. Ini berarti InheritedWidget terdekat di pohon memiliki prioritas — Anda dapat menimpa data pada level tertentu dengan menempatkan InheritedWidget lebih dekat ke turunan.

dart
class ThemeData {
  final Color primaryColor;
  final TextTheme textTheme;

  const ThemeData({required this.primaryColor, required this.textTheme});
}

class MyTheme extends InheritedWidget {
  final ThemeData data;

  const MyTheme({required this.data, required Widget child}) : super(child: child);

  static MyTheme of(BuildContext context) {
    final widget = context.dependOnInheritedWidgetOfExactType<MyTheme>();
    assert(widget != null, "MyTheme not found in tree");
    return widget!;
  }

  @override
  bool updateShouldNotify(MyTheme oldWidget) => oldWidget.data != data;
}

Dalam contoh ini, MyTheme menggunakan metode statis of untuk menyediakan data kepada turunan. Metode dependOnInheritedWidgetOfExactType mendaftarkan ketergantungan, dan updateShouldNotify membandingkan data lama dan baru untuk menentukan kebutuhan pembangunan ulang widget yang bergantung.

Membuat InheritedWidget sendiri

Membuat InheritedWidget sendiri terdiri dari dua langkah: mendefinisikan kelas yang mewarisi InheritedWidget dan mengimplementasikan metode statis of untuk akses dari turunan. Data dikirimkan melalui konstruktor, dan metode updateShouldNotify menentukan kapan widget yang bergantung harus dibangun ulang.

Langkah 1: Mendefinisikan kelas InheritedWidget

Kelas harus mewarisi InheritedWidget dan menerima data melalui konstruktor dengan parameter child wajib. Data dapat berupa tipe apa pun: primitif, objek, fungsi. Aturan utama — data harus bersifat immutable (tidak dapat diubah) agar dapat membandingkan nilai lama dan baru dengan andal.

Langkah 2: Metode statis of

Metode statis of menerima BuildContext dan mengembalikan data InheritedWidget. Di dalamnya, dependOnInheritedWidgetOfExactType dipanggil, yang mencari InheritedWidget terdekat dari tipe yang ditentukan di pohon. Jika InheritedWidget tidak ditemukan, metode melempar pengecualian atau mengembalikan nilai default tergantung pada implementasi.

Langkah 3: Penggunaan di widget

Untuk mengakses data, widget memanggil MyWidget.of(context) di dalam metode build. Flutter secara otomatis melanggankan widget pada pembaruan. Jika data berubah, widget akan dibangun ulang di frame berikutnya. Ini memungkinkan pembuatan kode yang bersih dan deklaratif tanpa parameter yang tidak perlu.

dart
class UserPreferences extends InheritedWidget {
  final String languageCode;
  final bool darkMode;

  const UserPreferences({
    required this.languageCode,
    required this.darkMode,
    required Widget child,
  }) : super(child: child);

  static UserPreferences of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<UserPreferences>()!;
  }

  @override
  bool updateShouldNotify(UserPreferences oldWidget) =>
    oldWidget.languageCode != languageCode || oldWidget.darkMode != darkMode;
}

Dalam contoh ini, UserPreferences menyimpan preferensi pengguna. Metode updateShouldNotify membandingkan setiap bidang secara terpisah, yang mencegah pembangunan ulang yang tidak perlu saat hanya satu parameter yang berubah. Gunakan pendekatan serupa untuk InheritedWidget Anda sendiri dengan banyak bidang.

Metode updateShouldNotify dan mencegah pembangunan ulang yang tidak perlu

updateShouldNotify — adalah metode kunci InheritedWidget yang menentukan apakah widget yang bergantung perlu diberi tahu tentang perubahan data. Jika metode mengembalikan false, widget yang bergantung tidak akan dibangun ulang, bahkan jika InheritedWidget sendiri menerima instance baru dengan data yang sama. Ini sangat penting untuk kinerja.

Implementasi updateShouldNotify yang benar

Bandingkan hanya bidang yang benar-benar berubah dan memengaruhi tampilan. Jika InheritedWidget berisi 10 bidang tetapi hanya satu yang memengaruhi UI, periksa hanya bidang itu. Untuk koleksi, gunakan perbandingan mendalam atau struktur data immutable. Jangan gunakan == untuk List atau Map, karena keduanya dibandingkan berdasarkan referensi.

  • Primitif — gunakan perbandingan langsung: oldWidget.value != value.
  • Objek immutable — gunakan == yang di-override: oldWidget.data != data (jika data meng-override ==).
  • Koleksi — gunakan listEquals, mapEquals dari package:flutter/foundation.dart.

Kesalahan dalam implementasi updateShouldNotify

Kesalahan paling umum — mengembalikan true tanpa perbandingan. Ini menyebabkan pembangunan ulang semua widget yang bergantung pada setiap pembaruan induk, bahkan jika data tidak berubah. Kesalahan kedua — mengembalikan false ketika data berubah, yang menyebabkan UI usang. Ketiga — perbandingan kompleks yang dijalankan setiap frame dan memperlambat kinerja.

InheritedWidget vs callback: mana yang harus dipilih?

InheritedWidget dan callback (pengiriman fungsi melalui konstruktor) menyelesaikan tugas yang berbeda. InheritedWidget cocok untuk data yang dibutuhkan banyak widget di berbagai level pohon. Callback berguna untuk pengiriman satu arah peristiwa dari induk ke anak tertentu atau sebaliknya. Pilihan tergantung pada arsitektur aplikasi dan frekuensi perubahan.

Kapan menggunakan InheritedWidget

Gunakan InheritedWidget ketika data dibutuhkan oleh banyak widget di berbagai tingkat penyarangan: tema aplikasi, preferensi pengguna, informasi perangkat, data sesi saat ini. InheritedWidget sangat efektif untuk data "global" yang jarang berubah tetapi diperlukan di berbagai bagian UI.

Kapan menggunakan callback

Callback (fungsi panggilan balik) cocok untuk mengirimkan peristiwa dari widget anak ke induk: penekanan tombol, pemilihan item daftar, pengiriman formulir. Callback secara eksplisit menunjukkan tindakan apa yang dapat dilakukan anak dan tidak menciptakan ketergantungan tersembunyi. Untuk mengirimkan data ke bawah pohon dalam jumlah level yang sedikit, menggunakan parameter konstruktor juga lebih sederhana.

KriteriaInheritedWidgetCallback
ArahDari atas ke bawah (induk → turunan)Dari bawah ke atas (anak → induk) atau langsung
JangkauanSeluruh subpohonWidget tertentu
Pembangunan ulangOtomatis saat data berubahMemerlukan setState manual
KompleksitasSedang (memerlukan kelas InheritedWidget)Rendah (fungsi sederhana)

InheritedWidget dan pustaka manajemen status

Provider dan Riverpod — pustaka manajemen status populer di Flutter, dibangun di atas InheritedWidget. Mereka memperluas kemampuannya: menambahkan dukungan ChangeNotifier, penghapusan otomatis saat pembongkaran, inisialisasi malas, dan sintaksis yang disederhanakan melalui generik.

Provider berbasis InheritedWidget

Provider menggunakan InheritedWidget untuk mengirimkan objek jenis apa pun ke bawah pohon. ChangeNotifierProvider melacak perubahan melalui ChangeNotifier dan memanggil updateShouldNotify saat notifyListeners dipanggil. Ini membebaskan pengembang dari pembuatan InheritedWidget secara manual dan implementasi updateShouldNotify.

Perbandingan dengan InheritedWidget langsung

InheritedWidget langsung memberikan lebih banyak kontrol dan tidak memerlukan ketergantungan eksternal. Provider menyediakan infrastruktur siap pakai: Consumer, Selector, MultiProvider, ProxyProvider. Pilihan tergantung pada kompleksitas aplikasi. Untuk proyek sederhana, InheritedWidget langsung sudah cukup; untuk proyek besar, Provider atau Riverpod mengurangi kode templat.

dart
// InheritedWidget langsung
class UserProvider extends InheritedWidget {
  final UserData userData;
  const UserProvider({required this.userData, required Widget child}) : super(child: child);
  static UserData of(BuildContext context) => context.dependOnInheritedWidgetOfExactType<UserProvider>()!.userData;
  @override
  bool updateShouldNotify(UserProvider old) => old.userData != userData;
}

// Setara Provider
return ChangeNotifierProvider<UserData>(
  create: (_) => UserData(),
  child: MyApp(),
);

Kedua pendekatan dalam contoh menyelesaikan tugas yang sama — mengirimkan UserData ke bawah pohon. Provider mengurangi jumlah kode tetapi menyembunyikan mekanika InheritedWidget. InheritedWidget langsung memberikan kontrol penuh dan pemahaman tentang apa yang terjadi, yang sangat penting saat mempelajari Flutter dan men-debug masalah pembangunan ulang yang kompleks.

Pertanyaan yang Sering Diajukan

Apa perbedaan InheritedWidget dengan widget biasa?

InheritedWidget membuat data dapat diakses oleh semua turunan melalui BuildContext, sedangkan widget biasa hanya mengirimkan data melalui konstruktor. InheritedWidget juga melanggankan turunan pada pembaruan data.

Seberapa sering widget yang bergantung dibangun ulang?

Widget yang bergantung hanya dibangun ulang ketika updateShouldNotify mengembalikan true. Jika metode diimplementasikan dengan benar, pembangunan ulang hanya terjadi saat data benar-benar berubah, bukan pada setiap rebuild induk.

Bisakah beberapa InheritedWidget digunakan dalam satu pohon?

Ya, Anda dapat menggunakan jumlah berapa pun InheritedWidget dalam satu pohon. Masing-masing menyediakan data tipe tertentu, dan widget dapat menerima data dari beberapa InheritedWidget secara bersamaan.

Apa perbedaan dependOnInheritedWidgetOfExactType dengan findAncestorWidgetOfExactType?

dependOn melanggankan widget pada pembaruan — saat data berubah, widget akan dibangun ulang. findAncestor melakukan pencarian satu kali tanpa langganan, dan widget tidak akan tahu tentang perubahan data.

Apakah InheritedWidget cocok untuk manajemen status yang kompleks?

Untuk status sederhana (tema, pengaturan) InheritedWidget sudah cukup. Untuk status kompleks dengan logika bisnis, gunakan Provider, Riverpod, atau BLoC — mereka dibangun di atas InheritedWidget dan menambahkan infrastruktur yang diperlukan.

Ringkasan

  • InheritedWidget — widget Flutter khusus untuk mengirimkan data ke bawah pohon dengan langganan pembaruan otomatis.
  • Mekanisme kerja didasarkan pada Element Tree: InheritedElement mendaftarkan elemen yang bergantung dan memberi tahu mereka tentang perubahan.
  • updateShouldNotify — metode kunci untuk mencegah pembangunan ulang widget yang bergantung yang tidak perlu.
  • InheritedWidget bawaan: Theme, MediaQuery, Localizations, Directionality, DefaultTextStyle.
  • Membuat InheritedWidget sendiri mencakup pewarisan kelas, pengiriman data melalui konstruktor, dan metode statis of.
  • Provider dan Riverpod dibangun di atas InheritedWidget dan menambahkan ChangeNotifier, Consumer, Selector, serta sintaksis yang disederhanakan.
  • InheritedWidget memecahkan masalah prop drilling dan merupakan fondasi manajemen status reaktif di Flutter.

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