InheritedWidget — ano ito, paglipat ng data sa puno at kung paano ito gumagana

May-akda: IT Sectr Nai-publish: 2026-07-02 Oras ng pagbabasa: 9 min

InheritedWidget — ay isang espesyal na widget sa Flutter na nagpapadala ng data pababa sa puno ng widget nang walang tahasang pagpasa sa pamamagitan ng mga konstruktor. Ang mga child widget ay nakakakuha ng access sa data sa pamamagitan ng BuildContext at awtomatikong nag-subscribe sa mga update. Kapag nagbago ang data sa InheritedWidget, lahat ng umaasang widget ay muling itinatayo. Ayon sa Flutter API Reference, 2025, ang InheritedWidget ay nasa pundasyon ng Theme, MediaQuery, Localizations at karamihan sa mga library ng pamamahala ng estado.

Mga Pangunahing Punto

  • InheritedWidget nagpapadala ng data pababa sa Widget Tree nang walang tahasang pagpasa sa bawat widget.
  • Awtomatikong subscription — ang mga widget na gumagamit ng dependOnInheritedWidgetOfExactType ay muling itinatayo kapag nagbago ang data.
  • Theme at MediaQuery — mga built-in na halimbawa ng InheritedWidget na available sa bawat Flutter app.
  • Provider at Riverpod ay binuo sa ibabaw ng InheritedWidget at pinapalawak ang mga kakayahan nito sa pamamahala ng estado.
  • Tamang implementasyon ay nangangailangan ng pag-override ng updateShouldNotify upang maiwasan ang hindi kinakailangang muling pagtatayo.

Ano ang InheritedWidget sa Flutter?

InheritedWidget — ay isang widget na ginagawang accessible ang data nito sa lahat ng mga inapo sa Widget Tree. Hindi tulad ng isang ordinaryong widget, na nagpapadala lamang ng data sa pamamagitan ng konstruktor sa mga child element, pinapayagan ng InheritedWidget ang sinumang widget sa sub-tree na ma-access ang data nang walang chain ng mga parameter. Nilulutas nito ang problema ng "prop drilling" — pagpapadala ng data sa pamamagitan ng maraming intermediary widget na hindi mismo gumagamit ng data na ito.

Mga built-in na InheritedWidget

Ang Flutter ay may kasamang ilang built-in na InheritedWidget: Theme (color scheme at styles), MediaQuery (laki ng screen, oryentasyon, pixel density), Localizations (na-localize na mga string), Directionality (direksyon ng teksto), DefaultTextStyle (default na style ng teksto). Ang mga widget na ito ay itinakda ng mga root widget tulad ng MaterialApp at available sa buong app.

Lifecycle ng InheritedWidget

InheritedWidget ay walang sariling estado — iniimbak nito ang data na ipinasa sa pamamagitan ng konstruktor. Kapag ang parent ng InheritedWidget ay muling itinayo gamit ang bagong data, ang updateShouldNotify na paraan ay tinatawag upang ihambing ang luma at bagong data. Kung ang paraan ay nagbalik ng true, lahat ng umaasang widget ay minamarkahan para sa muling pagtatayo. Ito ay isang simple ngunit epektibong mekanismo ng reaktibong pag-update.

Paano gumagana ang paglipat ng data sa pamamagitan ng InheritedWidget

Ang mekanismo ng paglipat ng data sa pamamagitan ng InheritedWidget ay batay sa Element Tree. Kapag ang isang widget ay tumawag ng dependOnInheritedWidgetOfExactType, ang kaukulang elemento ay nagrerehistro ng dependency sa InheritedElement. Kapag nagbago ang InheritedWidget, ang InheritedElement ay nag-aabiso sa lahat ng umaasang elemento, na muling itinatayo sa susunod na frame.

Pagrerehistro ng dependency

Ang paraang dependOnInheritedWidgetOfExactType ay hindi lamang nakakahanap ng InheritedWidget sa puno — ito ay nag-subscribe sa kasalukuyang elemento sa mga abiso. Kung gagamitin mo ang findAncestorWidgetOfExactType sa halip na dependOn, makakatanggap ang widget ng data ngunit hindi muling itatayo kapag nagbago ang mga ito. Ito ay isang mahalagang pagkakaiba: ang dependOn ay subscription, ang findAncestor ay isang beses na paghahanap.

Pag-navigate sa puno ng InheritedWidget

Kapag ang isang widget ay humiling ng InheritedWidget, ang Flutter ay umakyat sa Element Tree mula sa kasalukuyang elemento patungo sa ugat, sinusuri ang bawat InheritedElement para sa pagtutugma ng uri. Ang unang natagpuang InheritedElement ay ibinabalik. Ito ay nangangahulugan na ang pinakamalapit na InheritedWidget sa puno ay may priyoridad — maaari mong i-override ang data sa isang partikular na antas sa pamamagitan ng paglalagay ng InheritedWidget na mas malapit sa mga inapo.

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

Sa halimbawang ito, MyTheme ay gumagamit ng static na paraan na of upang magbigay ng data sa mga inapo. Ang dependOnInheritedWidgetOfExactType na paraan ay nagrerehistro ng dependency, at ang updateShouldNotify ay naghahambing ng luma at bagong data upang matukoy ang pangangailangan para sa muling pagtatayo ng mga umaasang widget.

Paglikha ng sarili mong InheritedWidget

Ang paglikha ng sarili mong InheritedWidget ay binubuo ng dalawang hakbang: pagtukoy ng klase na nagmamana ng InheritedWidget at pagpapatupad ng static na paraan na of para sa access mula sa mga inapo. Ang data ay ipinapasa sa pamamagitan ng konstruktor, at ang updateShouldNotify na paraan ay tumutukoy kung kailan dapat muling itayo ang mga umaasang widget.

Hakbang 1: Pagtukoy ng klase ng InheritedWidget

Ang klase ay dapat magmana ng InheritedWidget at tumanggap ng data sa pamamagitan ng konstruktor na may mandatoryong parameter na child. Ang data ay maaaring maging anumang uri: primitives, objects, functions. Ang pangunahing patakaran — ang data ay dapat na hindi nababago (immutable) upang mapagkakatiwalaang maihambing ang luma at bagong halaga.

Hakbang 2: Static na paraan na of

Ang static na paraan na of ay tumatanggap ng BuildContext at nagbabalik ng data ng InheritedWidget. Sa loob, ang dependOnInheritedWidgetOfExactType ay tinatawag, na naghahanap ng pinakamalapit na InheritedWidget ng tinukoy na uri sa puno. Kung hindi natagpuan ang InheritedWidget, ang paraan ay nagtatapon ng exception o nagbabalik ng default na halaga depende sa implementasyon.

Hakbang 3: Paggamit sa mga widget

Upang ma-access ang data, ang widget ay tumatawag ng MyWidget.of(context) sa loob ng build na paraan. Awtomatikong ini-subscribe ng Flutter ang widget sa mga update. Kung magbago ang data, ang widget ay muling itatayo sa susunod na frame. Ito ay nagpapahintulot sa paglikha ng malinis at deklaratibong code nang walang hindi kinakailangang mga parameter.

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

Sa halimbawang ito, UserPreferences ay nag-iimbak ng mga kagustuhan ng user. Ang updateShouldNotify na paraan ay naghahambing ng bawat field nang hiwalay, na pumipigil sa hindi kinakailangang muling pagtatayo kapag isang parameter lamang ang nagbago. Gumamit ng katulad na diskarte para sa iyong sariling InheritedWidget na may maraming field.

Ang updateShouldNotify na paraan at pag-iwas sa hindi kinakailangang muling pagtatayo

updateShouldNotify — ay ang pangunahing paraan ng InheritedWidget na tumutukoy kung kailangan bang abisuhan ang mga umaasang widget tungkol sa pagbabago ng data. Kung ang paraan ay nagbalik ng false, ang mga umaasang widget ay hindi muling itatayo, kahit na ang InheritedWidget mismo ay nakatanggap ng bagong instance na may parehong data. Ito ay kritikal para sa pagganap.

Tamang implementasyon ng updateShouldNotify

Ihambing lamang ang mga field na talagang nagbago at nakakaapekto sa pagpapakita. Kung ang InheritedWidget ay naglalaman ng 10 field ngunit isa lamang ang nakakaapekto sa UI, suriin lamang ang field na iyon. Para sa mga koleksyon, gumamit ng malalim na paghahambing o mga istraktura ng data na hindi nababago. Huwag gumamit ng == para sa List o Map, dahil ang mga ito ay inihahambing sa pamamagitan ng reference.

  • Primitives — gumamit ng direktang paghahambing: oldWidget.value != value.
  • Hindi nababagong mga bagay — gumamit ng na-override na ==: oldWidget.data != data (kung ang data ay nag-override ng ==).
  • Mga koleksyon — gumamit ng listEquals, mapEquals mula sa package:flutter/foundation.dart.

Mga pagkakamali sa implementasyon ng updateShouldNotify

Ang pinakakaraniwang pagkakamali — pagbabalik ng true nang walang paghahambing. Ito ay humahantong sa muling pagtatayo ng lahat ng umaasang widget sa bawat update ng parent, kahit na hindi nagbago ang data. Ang pangalawang pagkakamali — pagbabalik ng false kapag nagbago ang data, na humahantong sa lumang UI. Ang pangatlo — kumplikadong paghahambing na isinasagawa bawat frame at nagpapabagal sa pagganap.

InheritedWidget vs callback: alin ang pipiliin?

InheritedWidget at callback (pagpasa ng mga function sa pamamagitan ng konstruktor) ay lumulutas ng iba't ibang gawain. Ang InheritedWidget ay angkop para sa data na kailangan ng maraming widget sa iba't ibang antas ng puno. Ang callback ay maginhawa para sa one-way na pagpapadala ng mga kaganapan mula sa parent patungo sa isang partikular na child o kabaliktaran. Ang pagpili ay depende sa arkitektura ng app at dalas ng mga pagbabago.

Kailan gagamitin ang InheritedWidget

Gamitin ang InheritedWidget kapag ang data ay kailangan ng maraming widget sa iba't ibang antas ng pagkakasama-sama: tema ng app, mga kagustuhan ng user, impormasyon ng device, data ng kasalukuyang session. Ang InheritedWidget ay lalong epektibo para sa "global" na data na bihirang magbago ngunit kailangan sa iba't ibang bahagi ng UI.

Kailan gagamitin ang callback

Callback (mga function na pabalik) ay angkop para sa pagpapadala ng mga kaganapan mula sa child widget patungo sa parent: pagpindot ng button, pagpili ng item sa listahan, pagpapadala ng form. Ang callback ay tahasang nagpapakita kung anong mga aksyon ang maaaring gawin ng child at hindi lumilikha ng mga nakatagong dependency. Para sa pagpapadala ng data pababa sa puno sa maliit na bilang ng mga antas, mas simple ring gumamit ng mga parameter ng konstruktor.

KriteryaInheritedWidgetCallback
DireksyonMula sa itaas pababa (parent → mga inapo)Mula sa ibaba pataas (child → parent) o direkta
SaklawBuong sub-treeTiyak na widget
Muling pagtatayoAwtomatiko kapag nagbago ang dataNangangailangan ng manu-manong setState
KompleksidadKatamtaman (kailangan ng klase ng InheritedWidget)Mababa (simpleng function)

InheritedWidget at mga library ng pamamahala ng estado

Provider at Riverpod — mga sikat na library ng pamamahala ng estado sa Flutter, na binuo sa ibabaw ng InheritedWidget. Pinapalawak nila ang mga kakayahan nito: nagdaragdag ng suporta para sa ChangeNotifier, awtomatikong pag-alis kapag na-disassemble, lazy initialization at pinasimpleng syntax sa pamamagitan ng generics.

Provider batay sa InheritedWidget

Provider ay gumagamit ng InheritedWidget upang magpadala ng object ng anumang uri pababa sa puno. Ang ChangeNotifierProvider ay sumusubaybay ng mga pagbabago sa pamamagitan ng ChangeNotifier at tumatawag ng updateShouldNotify kapag tinawag ang notifyListeners. Ito ay nagpapalaya sa developer mula sa manu-manong paglikha ng InheritedWidget at pagpapatupad ng updateShouldNotify.

Paghahambing sa direktang InheritedWidget

Ang direktang InheritedWidget ay nagbibigay ng higit na kontrol at hindi nangangailangan ng mga panlabas na dependency. Ang Provider ay nagbibigay ng handa na imprastraktura: Consumer, Selector, MultiProvider, ProxyProvider. Ang pagpili ay depende sa kompleksidad ng app. Para sa mga simpleng proyekto, sapat na ang direktang InheritedWidget; para sa malalaking proyekto, ang Provider o Riverpod ay nagbabawas ng template code.

dart
// Direktang 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 katumbas
return ChangeNotifierProvider<UserData>(
  create: (_) => UserData(),
  child: MyApp(),
);

Ang parehong diskarte sa halimbawa ay lumulutas ng parehong gawain — pagpapadala ng UserData pababa sa puno. Provider ay nagbabawas ng dami ng code ngunit itinatago ang mekanika ng InheritedWidget. Ang direktang InheritedWidget ay nagbibigay ng buong kontrol at pag-unawa sa nangyayari, na lalong mahalaga kapag nag-aaral ng Flutter at nagde-debug ng mga kumplikadong problema sa muling pagtatayo.

Mga Madalas Itanong

Paano naiiba ang InheritedWidget sa ordinaryong widget?

InheritedWidget ay ginagawang accessible ang data sa lahat ng mga inapo sa pamamagitan ng BuildContext, habang ang ordinaryong widget ay nagpapadala lamang ng data sa pamamagitan ng konstruktor. Ang InheritedWidget ay nag-subscribe rin ng mga inapo sa mga update ng data.

Gaano kadalas muling itinatayo ang mga umaasang widget?

Ang mga umaasang widget ay muling itinatayo lamang kapag ang updateShouldNotify ay nagbalik ng true. Kung ang paraan ay naipatupad nang tama, ang muling pagtatayo ay nangyayari lamang kapag talagang nagbago ang data, hindi sa bawat rebuild ng parent.

Maaari bang gumamit ng maraming InheritedWidget sa iisang puno?

Oo, maaari kang gumamit ng anumang bilang ng InheritedWidget sa iisang puno. Bawat isa ay nagbibigay ng data ng isang partikular na uri, at ang mga widget ay maaaring makatanggap ng data mula sa maraming InheritedWidget nang sabay-sabay.

Paano naiiba ang dependOnInheritedWidgetOfExactType sa findAncestorWidgetOfExactType?

dependOn ay nag-subscribe ng widget sa mga update — kapag nagbago ang data, ang widget ay muling itatayo. findAncestor ay nagsasagawa ng isang beses na paghahanap nang walang subscription, at ang widget ay hindi malalaman ang tungkol sa mga pagbabago ng data.

Angkop ba ang InheritedWidget para sa pamamahala ng kumplikadong estado?

Para sa simpleng estado (tema, mga setting) sapat na ang InheritedWidget. Para sa kumplikadong estado na may business logic, gamitin ang Provider, Riverpod o BLoC — sila ay binuo sa ibabaw ng InheritedWidget at nagdaragdag ng kinakailangang imprastraktura.

Buod

  • InheritedWidget — isang espesyal na Flutter widget para sa pagpapadala ng data pababa sa puno na may awtomatikong subscription sa mga update.
  • Mekanismo ng paggana ay batay sa Element Tree: InheritedElement ay nagrerehistro ng mga umaasang elemento at nag-aabiso sa kanila tungkol sa mga pagbabago.
  • updateShouldNotify — pangunahing paraan upang maiwasan ang hindi kinakailangang muling pagtatayo ng mga umaasang widget.
  • Mga built-in na InheritedWidget: Theme, MediaQuery, Localizations, Directionality, DefaultTextStyle.
  • Paglikha ng sarili mong InheritedWidget ay kinabibilangan ng pagmamana ng klase, pagpasa ng data sa pamamagitan ng konstruktor at static na paraan na of.
  • Provider at Riverpod ay binuo sa ibabaw ng InheritedWidget at nagdaragdag ng ChangeNotifier, Consumer, Selector at pinasimpleng syntax.
  • InheritedWidget ay lumulutas ng problema ng prop drilling at ito ang pundasyon ng reaktibong pamamahala ng estado sa Flutter.

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din