InheritedWidget — bu nədir, ağacda məlumat ötürülməsi və necə işləyir

Müəllif: IT Sectr Dərc olunub: 2026-07-02 Oxuma vaxtı: 9 dəq

InheritedWidget — Flutter-da konstruktorlar vasitəsilə açıq ötürmədən vidjet ağacından aşağı məlumat ötürən xüsusi vidjetdir. Uşaq vidjetlər BuildContext vasitəsilə məlumatlara çıxış əldə edir və avtomatik olaraq yeniləmələrə abunə olur. InheritedWidget-də məlumatlar dəyişdikdə, bütün asılı vidjetlər yenidən qurulur. Flutter API Reference, 2025-ə görə, InheritedWidget Theme, MediaQuery, Localizations və vəziyyət idarəetmə kitabxanalarının əksəriyyətinin əsasını təşkil edir.

Əsas məqamlar

  • InheritedWidget hər vidjetdən açıq keçirmədən Widget Tree-dən aşağı məlumat ötürür.
  • Avtomatik abunə — dependOnInheritedWidgetOfExactType istifadə edən vidjetlər məlumat dəyişdikdə yenidən qurulur.
  • Theme və MediaQuery — hər Flutter tətbiqində mövcud olan daxili InheritedWidget nümunələri.
  • Provider və Riverpod InheritedWidget üzərində qurulub və onun vəziyyət idarəetmə imkanlarını genişləndirir.
  • Düzgün tətbiq lazımsız yenidən qurmaların qarşısını almaq üçün updateShouldNotify-in dəyişdirilməsini tələb edir.

Flutter-da InheritedWidget nədir?

InheritedWidget — Widget Tree-də məlumatlarını bütün nəsillərə əlçatan edən vidjetdir. Adi vidjetdən fərqli olaraq, məlumatları yalnız konstruktor vasitəsilə uşaq elementlərə ötürən InheritedWidget, alt ağacdakı istənilən vidjetə parametr zənciri olmadan məlumatlara çıxış imkanı verir. Bu, "prop drilling" problemini həll edir — bu məlumatlardan özləri istifadə etməyən çoxsaylı aralıq vidjetlər vasitəsilə məlumat ötürülməsi.

Daxili InheritedWidget

Flutter bir neçə daxili InheritedWidget ehtiva edir: Theme (rəng sxemi və stillər), MediaQuery (ekran ölçüsü, oriyentasiya, piksel sıxlığı), Localizations (lokallaşdırılmış sətirlər), Directionality (mətn istiqaməti), DefaultTextStyle (standart mətn stili). Bu vidjetlər MaterialApp kimi kök vidjetlər tərəfindən qurulur və bütün tətbiqdə əlçatandır.

InheritedWidget-in həyat dövrü

InheritedWidget öz vəziyyətinə malik deyil — konstruktor vasitəsilə ötürülən məlumatları saxlayır. InheritedWidget-in valideyni yeni məlumatlarla yenidən qurulduqda, köhnə və yeni məlumatları müqayisə etmək üçün updateShouldNotify metodu çağırılır. Metod true qaytararsa, bütün asılı vidjetlər yenidən qurulma üçün işarələnir. Bu, reaktiv yeniləmənin sadə, lakin effektiv mexanizmidir.

InheritedWidget vasitəsilə məlumat ötürülməsi necə işləyir

Məlumat ötürmə mexanizmi InheritedWidget vasitəsilə Element Tree-ə əsaslanır. Vidjet dependOnInheritedWidgetOfExactType çağırdıqda, müvafiq element InheritedElement-dən asılılığı qeydiyyatdan keçirir. InheritedWidget dəyişdikdə, InheritedElement bütün asılı elementlərə xəbərdarlıq edir və onlar növbəti kadrda yenidən qurulur.

Asılılığın qeydiyyatı

dependOnInheritedWidgetOfExactType metodu sadəcə ağacda InheritedWidget tapmır — cari elementi bildirişlərə abunə edir. Əgər dependOn əvəzinə findAncestorWidgetOfExactType istifadə etsəydiniz, vidjet məlumatları alardı, lakin onlar dəyişdikdə yenidən qurulmazdı. Bu vacib fərqdir: dependOn — abunə, findAncestor — birdəfəlik axtarışdır.

InheritedWidget ağacında gəzinti

Vidjet InheritedWidget tələb etdikdə, Flutter cari elementdən kökə qədər Element Tree boyunca yüksəlir, hər InheritedElement-i tip uyğunluğu üçün yoxlayır. İlk tapılan InheritedElement qaytarılır. Bu o deməkdir ki, ağacdakı ən yaxın InheritedWidget prioritetə malikdir — InheritedWidget-i nəsillərə daha yaxın yerləşdirərək müəyyən səviyyədə məlumatları dəyişə bilərsiniz.

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;
}

Bu nümunədə MyTheme nəsillərə məlumat təqdim etmək üçün statik of metodundan istifadə edir. dependOnInheritedWidgetOfExactType metodu asılılığı qeydiyyatdan keçirir, updateShouldNotify isə asılı vidjetlərin yenidən qurulma zərurətini müəyyən etmək üçün köhnə və yeni məlumatları müqayisə edir.

Öz InheritedWidget-nizi yaratmaq

Öz InheritedWidget-nizi yaratmaq iki addımdan ibarətdir: InheritedWidget-dən miras alan sinifin müəyyən edilməsi və nəsillərdən giriş üçün statik of metodunun tətbiqi. Məlumatlar konstruktor vasitəsilə ötürülür, updateShouldNotify metodu isə asılı vidjetlərin nə vaxt yenidən qurulmalı olduğunu müəyyən edir.

Addım 1: InheritedWidget sinifinin təyini

Sinif InheritedWidget-dən miras almalı və məcburi child parametri ilə konstruktor vasitəsilə məlumatları qəbul etməlidir. Məlumatlar istənilən tipdə ola bilər: primitivlər, obyektlər, funksiyalar. Əsas qayda — məlumatlar dəyişməz (immutable) olmalıdır ki, köhnə və yeni dəyərləri etibarlı şəkildə müqayisə etmək mümkün olsun.

Addım 2: Statik of metodu

Statik of metodu BuildContext qəbul edir və InheritedWidget məlumatlarını qaytarır. Daxildə ağacda göstərilən tipin ən yaxın InheritedWidget-ni axtaran dependOnInheritedWidgetOfExactType çağırılır. InheritedWidget tapılmazsa, metod tətbiqdən asılı olaraq ya istisna atır, ya da standart dəyər qaytarır.

Addım 3: Vidjetlərdə istifadə

Məlumatlara giriş üçün vidjet build metodu daxilində MyWidget.of(context) çağırır. Flutter avtomatik olaraq vidjeti yeniləmələrə abunə edir. Məlumatlar dəyişərsə, vidjet növbəti kadrda yenidən qurulacaq. Bu, lazımsız parametrlər olmadan təmiz və deklarativ kod yaratmağa imkan verir.

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;
}

Bu nümunədə UserPreferences istifadəçi tənzimləmələrini saxlayır. updateShouldNotify metodu hər sahəni ayrıca müqayisə edir ki, bu da yalnız bir parametr dəyişdikdə lazımsız yenidən qurmaların qarşısını alır. Çox sahəli öz InheritedWidget-niz üçün oxşar yanaşmadan istifadə edin.

updateShouldNotify metodu və lazımsız yenidən qurmaların qarşısının alınması

updateShouldNotify — məlumat dəyişikliyi haqqında asılı vidjetlərə xəbərdarlıq edilməsinin zəruri olub-olmadığını müəyyən edən InheritedWidget-in əsas metodudur. Metod false qaytararsa, asılı vidjetlər, hətta InheritedWidget eyni məlumatlarla yeni nümunə alsa belə, yenidən qurulmur. Bu, performans üçün kritik əhəmiyyət daşıyır.

updateShouldNotify-in düzgün tətbiqi

Yalnız həqiqətən dəyişən və göstərilməyə təsir edən sahələri müqayisə edin. InheritedWidget 10 sahə ehtiva edirsə, lakin onlardan yalnız biri UI-yə təsir edirsə, yalnız həmin sahəni yoxlayın. Kolleksiyalar üçün dərin müqayisə və ya dəyişməz məlumat strukturlarından istifadə edin. List və ya Map üçün == istifadə etməyin, çünki onlar istinadla müqayisə edilir.

  • Primitivlər — birbaşa müqayisələrdən istifadə edin: oldWidget.value != value.
  • Dəyişməz obyektlər — dəyişdirilmiş == istifadə edin: oldWidget.data != data (əgər data == dəyişdirirsə).
  • Kolleksiyalar — package:flutter/foundation.dart-dən listEquals, mapEquals istifadə edin.

updateShouldNotify tətbiqində səhvlər

Ən çox yayılmış səhv — müqayisəsiz true qaytarmaq. Bu, hətta məlumatlar dəyişmədikdə belə, valideynin hər yenilənməsində bütün asılı vidjetlərin yenidən qurulmasına gətirib çıxarır. İkinci səhv — məlumatlar dəyişdikdə false qaytarmaq, bu da köhnəlmiş UI-ya səbəb olur. Üçüncüsü — hər kadrda yerinə yetirilən və işi ləngidən mürəkkəb müqayisədir.

InheritedWidget vs callbacklər: nə seçməli?

InheritedWidget və callbacklər (funksiyaların konstruktor vasitəsilə ötürülməsi) müxtəlif vəzifələri həll edir. InheritedWidget ağacın müxtəlif səviyyələrində çoxlu vidjetlərə lazım olan məlumatlar üçün uyğundur. Callbacklər hadisələrin valideyndən konkret nəslə və ya əksinə biristiqamətli ötürülməsi üçün əlverişlidir. Seçim tətbiqin arxitekturasından və dəyişiklik tezliyindən asılıdır.

InheritedWidget nə vaxt istifadə edilməlidir

InheritedWidget-dən məlumatlar çoxlu vidjetlərə müxtəlif yuvalanma səviyyələrində lazım olduqda istifadə edin: tətbiq mövzusu, istifadəçi tənzimləmələri, cihaz məlumatı, cari sessiya məlumatları. InheritedWidget xüsusilə nadir dəyişən, lakin UI-nin müxtəlif hissələrində lazım olan "qlobal" məlumatlar üçün effektivdir.

Callbacklər nə vaxt istifadə edilməlidir

Callbacklər (qaytarma funksiyaları) hadisələrin uşaq vidjetdən valideynə ötürülməsi üçün uyğundur: düyməyə basma, siyahı elementinin seçilməsi, formanın göndərilməsi. Callbacklər nəslin hansı hərəkətləri yerinə yetirə biləcəyini açıq şəkildə göstərir və gizli asılılıqlar yaratmır. Ağacdan aşağı az sayda səviyyə üçün məlumat ötürmək üçün konstruktor parametrlərindən istifadə etmək daha sadədir.

KriteriyaInheritedWidgetCallbacklər
İstiqamətYuxarıdan aşağı (valideyn → nəsillər)Aşağıdan yuxarı (nəsil → valideyn) və ya birbaşa
ƏhatəBütün alt ağacKonkret vidjet
Yenidən qurmaMəlumat dəyişdikdə avtomatikƏllə setState tələb edir
MürəkkəblikOrta (InheritedWidget sinifi lazımdır)Aşağı (sadə funksiya)

InheritedWidget və vəziyyət idarəetmə kitabxanaları

ProviderRiverpod — InheritedWidget üzərində qurulmuş Flutter-da məşhur vəziyyət idarəetmə kitabxanalarıdır. Onlar onun imkanlarını genişləndirir: ChangeNotifier dəstəyi, sökülmə zamanı avtomatik silmə, gec başlatma və generiklər vasitəsilə sadələşdirilmiş sintaksis əlavə edirlər.

InheritedWidget əsasında Provider

Provider istənilən tip obyekti ağacdan aşağı ötürmək üçün InheritedWidget-dən istifadə edir. ChangeNotifierProvider ChangeNotifier vasitəsilə dəyişiklikləri izləyir və notifyListeners çağırıldıqda updateShouldNotify çağırır. Bu, tərtibatçını əl ilə InheritedWidget yaratmaqdan və updateShouldNotify tətbiq etməkdən azad edir.

Birbaşa InheritedWidget ilə müqayisə

Birbaşa InheritedWidget daha çox nəzarət verir və xarici asılılıqlar tələb etmir. Provider hazır infrastruktur təmin edir: Consumer, Selector, MultiProvider, ProxyProvider. Seçim tətbiqin mürəkkəbliyindən asılıdır. Sadə layihələr üçün birbaşa InheritedWidget kifayətdir, böyük layihələr üçün Provider və ya Riverpod şablon kodu azaldır.

dart
// Birbaşa 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(),
);

Nümunədə hər iki yanaşma eyni tapşırığı həll edir — UserData-nı ağacdan aşağı ötürmək. Provider kodun miqdarını azaldır, lakin InheritedWidget mexanikasını gizlədir. Birbaşa InheritedWidget tam nəzarət və baş verənlərin başa düşülməsini təmin edir ki, bu da xüsusilə Flutter öyrənərkən və yenidən qurma ilə bağlı mürəkkəb problemlərin aradan qaldırılmasında vacibdir.

Tez-tez verilən suallar

InheritedWidget adi vidjetdən nə ilə fərqlənir?

InheritedWidget məlumatları BuildContext vasitəsilə bütün nəsillərə əlçatan edir, adi vidjet isə məlumatları yalnız konstruktor vasitəsilə ötürür. InheritedWidget həmçinin nəsilləri məlumat yeniləmələrinə abunə edir.

Asılı vidjetlər nə qədər tez-tez yenidən qurulur?

Asılı vidjetlər yalnız updateShouldNotify true qaytardıqda yenidən qurulur. Metod düzgün tətbiq edilərsə, yenidən qurma yalnız məlumatlar həqiqətən dəyişdikdə baş verir, valideynin hər rebuild-ində deyil.

Bir ağacda bir neçə InheritedWidget istifadə etmək olarmı?

Bəli, bir ağacda istənilən sayda InheritedWidget istifadə etmək olar. Hər biri müəyyən tip məlumat təmin edir, vidjetlər isə eyni anda bir neçə InheritedWidget-dən məlumat ala bilər.

dependOnInheritedWidgetOfExactType findAncestorWidgetOfExactType-dən nə ilə fərqlənir?

dependOn vidjeti yeniləmələrə abunə edir — məlumat dəyişdikdə vidjet yenidən qurulacaq. findAncestor abunəsiz birdəfəlik axtarış aparır və vidjet məlumat dəyişikliklərindən xəbərsiz qalacaq.

InheritedWidget mürəkkəb vəziyyəti idarə etmək üçün uyğundurmu?

Sadə vəziyyət (mövzu, tənzimləmələr) üçün InheritedWidget kifayətdir. Biznes məntiqi ilə mürəkkəb vəziyyət üçün Provider, Riverpod və ya BLoC istifadə edin — onlar InheritedWidget üzərində qurulub və lazımi infrastrukturu əlavə edir.

Xülasə

  • InheritedWidget — avtomatik yeniləmə abunəsi ilə ağacdan aşağı məlumat ötürmək üçün xüsusi Flutter vidjeti.
  • İş mexanizmi Element Tree-ə əsaslanır: InheritedElement asılı elementləri qeydiyyatdan keçirir və onlara dəyişikliklər barədə məlumat verir.
  • updateShouldNotify — asılı vidjetlərin lazımsız yenidən qurulmasının qarşısını almaq üçün əsas metod.
  • Daxili InheritedWidget: Theme, MediaQuery, Localizations, Directionality, DefaultTextStyle.
  • Öz InheritedWidget-nizi yaratmaq sinifdən miras almağı, konstruktor vasitəsilə məlumat ötürməyi və statik of metodunu əhatə edir.
  • Provider və Riverpod InheritedWidget üzərində qurulub və ChangeNotifier, Consumer, Selector və sadələşdirilmiş sintaksis əlavə edir.
  • InheritedWidget prop drilling problemini həll edir və Flutter-da reaktiv vəziyyət idarəetməsinin əsasını təşkil edir.

Açar təslim mobil tətbiq hazırlayacağıq

IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.

Layihəni müzakirə et

Həm də oxuyun