InheritedWidget — bu Flutter-da konstruktorlar orqali aniq uzatmasdan vidjetlar daraxtidan pastga ma'lumot uzatuvchi maxsus vidjetdir. Farzand vidjetlar BuildContext orqali ma'lumotlarga kirishadi va avtomatik ravishda yangilanishlarga obuna bo'ladi. InheritedWidget-dagi ma'lumotlar o'zgarganda, barcha bog'liq vidjetlar qayta quriladi. Flutter API Reference, 2025 ma'lumotlariga ko'ra, InheritedWidget Theme, MediaQuery, Localizations va holat boshqaruv kutubxonalarining aksariyatining asosini tashkil qiladi.
Asosiy fikrlar
InheritedWidget — bu Widget Tree-da o'z ma'lumotlarini barcha avlodlarga mavjud qiladigan vidjetdir. Oddiy vidjetdan farqli o'laroq, ma'lumotlarni faqat konstruktor orqali farzand elementlarga uzatadigan InheritedWidget, pastki daraxtdagi istalgan vidjetga parametr zanjirisiz ma'lumotlarga kirish imkonini beradi. Bu "prop drilling" muammosini hal qiladi — bu ma'lumotlardan o'zlari foydalanmaydigan ko'plab oraliq vidjetlar orqali ma'lumot uzatish.
Flutter bir nechta o'rnatilgan InheritedWidget-ni o'z ichiga oladi: Theme (rang sxemasi va stillar), MediaQuery (ekran o'lchami, orientatsiya, piksel zichligi), Localizations (mahalliylashtirilgan satrlar), Directionality (matn yo'nalishi), DefaultTextStyle (standart matn uslubi). Bu vidjetlar MaterialApp kabi ildiz vidjetlar tomonidan o'rnatiladi va butun ilovada mavjud.
InheritedWidget o'z holatiga ega emas — konstruktor orqali uzatilgan ma'lumotlarni saqlaydi. InheritedWidget-ning ota-onasi yangi ma'lumotlar bilan qayta qurilganda, eski va yangi ma'lumotlarni solishtirish uchun updateShouldNotify metodi chaqiriladi. Agar metod true qaytarsa, barcha bog'liq vidjetlar qayta qurish uchun belgilanadi. Bu reaktiv yangilanishning sodda, ammo samarali mexanizmidir.
Ma'lumot uzatish mexanizmi InheritedWidget orqali Element Tree-ga asoslanadi. Vidjet dependOnInheritedWidgetOfExactType-ni chaqirganda, tegishli element InheritedElement-dan bog'liqlikni ro'yxatdan o'tkazadi. InheritedWidget o'zgarganda, InheritedElement barcha bog'liq elementlarni xabardor qiladi va ular keyingi kadrda qayta quriladi.
dependOnInheritedWidgetOfExactType metodi nafaqat daraxtda InheritedWidget-ni topadi — u joriy elementni bildirishnomalarga obuna qiladi. Agar dependOn o'rniga findAncestorWidgetOfExactType ishlatganingizda, vidjet ma'lumotlarni olar edi, lekin ular o'zgarganda qayta qurilmas edi. Bu muhim farq: dependOn — obuna, findAncestor — bir martalik qidiruv.
Vidjet InheritedWidget-ni so'raganda, Flutter joriy elementdan ildizgacha Element Tree bo'ylab ko'tariladi, har bir InheritedElement-ni tur mosligi uchun tekshiradi. Birinchi topilgan InheritedElement qaytariladi. Bu daraxtdagi eng yaqin InheritedWidget ustunlikka ega degani — InheritedWidget-ni avlodlarga yaqinroq joylashtirib, ma'lum bir darajadagi ma'lumotlarni bekor qilishingiz mumkin.
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;
}
Bu misolda MyTheme avlodlarga ma'lumot taqdim etish uchun statik of metodidan foydalanadi. dependOnInheritedWidgetOfExactType metodi bog'liqlikni ro'yxatdan o'tkazadi, updateShouldNotify esa bog'liq vidjetlarning qayta qurilish zaruriyatini aniqlash uchun eski va yangi ma'lumotlarni solishtiradi.
O'z InheritedWidget-ingizni yaratish ikki qadamdan iborat: InheritedWidget-dan meros oladigan sinfni aniqlash va avlodlardan kirish uchun statik of metodini tatbiq qilish. Ma'lumotlar konstruktor orqali uzatiladi, updateShouldNotify metodi esa bog'liq vidjetlarning qachon qayta qurilishi kerakligini aniqlaydi.
Sinf InheritedWidget-dan meros olishi va majburiy child parametri bilan konstruktor orqali ma'lumotlarni qabul qilishi kerak. Ma'lumotlar istalgan turda bo'lishi mumkin: primitivlar, ob'ektlar, funksiyalar. Asosiy qoida — ma'lumotlar o'zgarmas (immutable) bo'lishi kerak, shunda eski va yangi qiymatlarni ishonchli solishtirish mumkin.
Statik of metodi BuildContext qabul qiladi va InheritedWidget ma'lumotlarini qaytaradi. Ichkarida daraxtda belgilangan turdagi eng yaqin InheritedWidget-ni qidiradigan dependOnInheritedWidgetOfExactType chaqiriladi. Agar InheritedWidget topilmasa, metod tatbiqqa qarab istisno tashlaydi yoki standart qiymat qaytaradi.
Ma'lumotlarga kirish uchun vidjet build metodi ichida MyWidget.of(context)-ni chaqiradi. Flutter avtomatik ravishda vidjetni yangilanishlarga obuna qiladi. Agar ma'lumotlar o'zgarsa, vidjet keyingi kadrda qayta quriladi. Bu keraksiz parametrlarsiz toza va deklarativ kod yaratishga imkon beradi.
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;
}
Bu misolda UserPreferences foydalanuvchi sozlamalarini saqlaydi. updateShouldNotify metodi har bir maydonni alohida solishtiradi, bu faqat bitta parametr o'zgarganda keraksiz qayta qurilishlarning oldini oladi. Bir nechta maydonli o'z InheritedWidget-ingiz uchun shunday yondashuvdan foydalaning.
updateShouldNotify — ma'lumotlar o'zgarishi haqida bog'liq vidjetlarni xabardor qilish kerakligini aniqlaydigan InheritedWidget-ning asosiy metodidir. Agar metod false qaytarsa, bog'liq vidjetlar, hatto InheritedWidget bir xil ma'lumotlar bilan yangi nusxa olgan bo'lsa ham, qayta qurilmaydi. Bu ishlash uchun juda muhim.
Faqat haqiqatan o'zgargan va ko'rinishga ta'sir qiladigan maydonlarni solishtiring. Agar InheritedWidget 10 ta maydonni o'z ichiga olsa, lekin ulardan faqat bittasi UI-ga ta'sir qilsa, faqat shu maydonni tekshiring. To'plamlar uchun chuqur solishtirish yoki o'zgarmas ma'lumot tuzilmalaridan foydalaning. List yoki Map uchun == ishlatmang, chunki ular havola orqali solishtiriladi.
Eng keng tarqalgan xato — solishtirishsiz true qaytarish. Bu ma'lumotlar o'zgarmagan bo'lsa ham, ota-onaning har bir yangilanishida barcha bog'liq vidjetlarning qayta qurilishiga olib keladi. Ikkinchi xato — ma'lumotlar o'zgarganda false qaytarish, bu eskirgan UI-ga sabab bo'ladi. Uchinchisi — har bir kadrda bajariladigan va ishni sekinlashtiradigan murakkab solishtirish.
InheritedWidget va callbacklar (funksiyalarni konstruktor orqali uzatish) turli vazifalarni hal qiladi. InheritedWidget daraxtning turli darajalarida ko'plab vidjetlarga kerak bo'lgan ma'lumotlar uchun mos keladi. Callbacklar hodisalarni ota-onadan ma'lum bir farzandga yoki aksincha bir yo'nalishli uzatish uchun qulaydir. Tanlov ilova arxitekturasi va o'zgarishlar chastotasiga bog'liq.
InheritedWidget-dan ma'lumotlar ko'plab vidjetlarga turli joylashtirish darajalarida kerak bo'lganda foydalaning: ilova mavzusi, foydalanuvchi sozlamalari, qurilma ma'lumotlari, joriy sessiya ma'lumotlari. InheritedWidget, ayniqsa, kamdan-kam o'zgaradigan, lekin UI ning turli qismlarida kerak bo'lgan "global" ma'lumotlar uchun samarali.
Callbacklar (qaytarish funksiyalari) hodisalarni farzand vidjetdan ota-onaga uzatish uchun mos keladi: tugmani bosish, ro'yxat elementini tanlash, formani yuborish. Callbacklar farzand qanday harakatlarni bajarishi mumkinligini aniq ko'rsatadi va yashirin bog'liqliklarni yaratmaydi. Daraxtdan pastga oz sonli darajalar uchun ma'lumot uzatishda konstruktor parametrlaridan foydalanish ham soddaroq.
| Mezon | InheritedWidget | Callbacklar |
|---|---|---|
| Yo'nalish | Yuqoridan pastga (ota-ona → avlodlar) | Pastdan yuqoriga (farzand → ota-ona) yoki to'g'ridan-to'g'ri |
| Qamrov | Butun pastki daraxt | Muayyan vidjet |
| Qayta qurish | Ma'lumot o'zgarganda avtomatik | Qo'lda setState talab qiladi |
| Murakkablik | O'rtacha (InheritedWidget sinfi kerak) | Past (oddiy funksiya) |
Provider va Riverpod — InheritedWidget asosida qurilgan Flutter-dagi mashhur holat boshqaruv kutubxonalari. Ular uning imkoniyatlarini kengaytiradi: ChangeNotifier qo'llab-quvvatlashi, demontajda avtomatik o'chirish, kechiktirilgan ishga tushirish va generiklar orqali soddalashtirilgan sintaksis qo'shadi.
Provider istalgan turdagi ob'ektni daraxtdan pastga uzatish uchun InheritedWidget-dan foydalanadi. ChangeNotifierProvider ChangeNotifier orqali o'zgarishlarni kuzatadi va notifyListeners chaqirilganda updateShouldNotify-ni chaqiradi. Bu dasturchini qo'lda InheritedWidget yaratish va updateShouldNotify tatbiq qilishdan ozod qiladi.
To'g'ridan-to'g'ri InheritedWidget ko'proq nazorat beradi va tashqi bog'liqliklarni talab qilmaydi. Provider tayyor infratuzilmani taqdim etadi: Consumer, Selector, MultiProvider, ProxyProvider. Tanlov ilovaning murakkabligiga bog'liq. Oddiy loyihalar uchun to'g'ridan-to'g'ri InheritedWidget yetarli, katta loyihalar uchun Provider yoki Riverpod shablon kodini kamaytiradi.
// To'g'ridan-to'g'ri InheritedWidget
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;
}
// Provider ekvivalenti
return ChangeNotifierProvider<UserData>(
create: (_) => UserData(),
child: MyApp(),
);
Misoldagi ikkala yondashuv bir xil vazifani hal qiladi — UserData-ni daraxtdan pastga uzatish. Provider kod miqdorini kamaytiradi, lekin InheritedWidget mexanikasini yashiradi. To'g'ridan-to'g'ri InheritedWidget to'liq nazorat va sodir bo'layotgan voqealarni tushunishni ta'minlaydi, bu ayniqsa Flutter-ni o'rganishda va qayta qurish bilan bog'liq murakkab muammolarni bartaraf etishda muhim.
Tez-tez so'raladigan savollar
InheritedWidget ma'lumotlarni BuildContext orqali barcha avlodlarga mavjud qiladi, oddiy vidjet esa ma'lumotlarni faqat konstruktor orqali uzatadi. InheritedWidget shuningdek avlodlarni ma'lumot yangilanishlariga obuna qiladi.
Bog'liq vidjetlar faqat updateShouldNotify true qaytarganda qayta quriladi. Agar metod to'g'ri tatbiq qilingan bo'lsa, qayta qurish faqat ma'lumotlar haqiqatan o'zgarganda sodir bo'ladi, ota-onaning har bir rebuild-idagina emas.
Ha, bitta daraxtda istalgan miqdorda InheritedWidget ishlatish mumkin. Har biri ma'lum bir turdagi ma'lumotlarni taqdim etadi, vidjetlar esa bir vaqtning o'zida bir nechta InheritedWidget-dan ma'lumot olishi mumkin.
dependOn vidjetni yangilanishlarga obuna qiladi — ma'lumot o'zgarganda vidjet qayta quriladi. findAncestor obunasiz bir martalik qidiruvni amalga oshiradi va vidjet ma'lumot o'zgarishlaridan xabardor bo'lmaydi.
Oddiy holat (mavzu, sozlamalar) uchun InheritedWidget yetarli. Biznes mantiqi bilan murakkab holat uchun Provider, Riverpod yoki BLoC dan foydalaning — ular InheritedWidget asosida qurilgan va kerakli infratuzilmani qo'shadi.
Xulosa
Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz
IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.