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 — 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.
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.
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.
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.
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.
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.
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 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.
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.
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.
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.
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.
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.
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.
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 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.
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.
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.
| Kriteria | InheritedWidget | Callback |
|---|---|---|
| Arah | Dari atas ke bawah (induk → turunan) | Dari bawah ke atas (anak → induk) atau langsung |
| Jangkauan | Seluruh subpohon | Widget tertentu |
| Pembangunan ulang | Otomatis saat data berubah | Memerlukan setState manual |
| Kompleksitas | Sedang (memerlukan kelas InheritedWidget) | Rendah (fungsi sederhana) |
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 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.
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.
// 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
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.
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.
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.
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.
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
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.
Baca juga