flutter-狀態(tài)管理2-inheritedWidget探究

inheritedWidget是如何實(shí)現(xiàn)數(shù)據(jù)共享的?

要解決這個(gè)問(wèn)題,首先我們先看下,這個(gè)數(shù)據(jù)是如何存取的,又是如何刷新的.

一. _inheritedWidgets的存取

這個(gè)問(wèn)題的奧秘其實(shí)就在Element中.


element內(nèi)部有一個(gè)_inheritedWidgets.png

我們先來(lái)看一下inheritedWidget數(shù)據(jù)共享使用過(guò)程中的這個(gè)Map存取:

取:

通常我們使用inheritedWidget的時(shí)候,都是會(huì)有一個(gè)取數(shù)據(jù)的過(guò)程,這個(gè)時(shí)候我們會(huì)通過(guò)子節(jié)點(diǎn)的BuildContext(Element是BuildContext的實(shí)現(xiàn)類,使用context.getElementForInheritedWidgetOfExactType() 或 context.dependOnInheritedWidgetOfExactType來(lái)獲取到這個(gè)widget或element從而獲取到數(shù)據(jù)(例如上次講的例子).

image.png

查看這兩個(gè)方法,在Element中,都是從 _inheritedWidgets這個(gè)map里取值,泛型T是key


Element中的實(shí)現(xiàn).png

存:

Element中.png

InhertiedElement中重寫(xiě)了這個(gè)_updateInheritance()方法:
若父節(jié)點(diǎn)的_inheritedWidgets不為空,將其深拷貝給子節(jié)點(diǎn)的_inheritedWidgets;
若父節(jié)點(diǎn)的_inheritedWidgets為空,初始化一個(gè)Map,key為其widget的runtimeType


InhertiedElement中.png

我們可以看到,element中有Map<Type, InheritedElement>? _inheritedWidgets成員變量,這個(gè)成員變量一般情況下是空的,只有當(dāng)父控件或本身是InheritedWidget的時(shí)候, _inheritedWidgets才會(huì)被初始化.
當(dāng)父控件是InheritedWidget是,這個(gè)Map會(huì)在Element中被一級(jí)一級(jí)的向下傳遞與合并.

image.png

二. dependOnInheritedWidgetOfExactType方法中到底做了什么

通過(guò)element中對(duì)此方法的描述及InheritedElement中此方法的實(shí)現(xiàn),可以看出:

  • 1. 從_inheritedWidgets中查找是否有該類型的InheritedElement
  • 2. 查找到有的話,執(zhí)行dependOnInheritedElement方法,將它添加到_dependencies里面; 并且調(diào)用ancestor.updateDependencies(this, aspect), 將當(dāng)前Element添加到_dependents(Map<Element, Object?> _dependents)里面
    Element中.png

    image.png

    image.png

    image.png
  • 3.返回這個(gè)element對(duì)應(yīng)的widget (dependOnInheritedElement方法中)

三. getElementForInheritedWidgetOfExactType與dependOnInheritedWidgetOfExactType的區(qū)別

image.png

通過(guò)上圖我們也可以看出, 兩個(gè)方法的主要區(qū)別在于, getElementForInheritedWidgetOfExactType是直接獲取了_inheritedWidgets內(nèi)的InheritedElement返回;而dependOnInheritedWidgetOfExactType在獲取的過(guò)程中,還多做了一步_dependents的管理,將_inheritedWidgets中的依賴關(guān)系管理起來(lái)

當(dāng)inheritedWidget被更新時(shí), _dependents中的element會(huì)被逐個(gè)執(zhí)行notifyDependent,最后觸發(fā)markNeedsBuild進(jìn)行重繪.


image.png

image.png
image.png

當(dāng)執(zhí)行notifyDependent時(shí),會(huì)觸發(fā)Element的didChangeDependencies方法,將_didChangeDependencies置為true,從而觸發(fā)State的didChangeDependencies的回調(diào)生命周期


image.png

image.png

總結(jié)

所以,當(dāng)我們inheritedWidget來(lái)實(shí)現(xiàn)數(shù)據(jù)共享的時(shí)候,需要注意兩個(gè)點(diǎn)

  • 1.使用的context,必須是inheritedWidget的child widget對(duì)應(yīng)的context---(Element)
  • 2.getElementForInheritedWidgetOfExactType和dependOnInheritedWidgetOfExactType的區(qū)別
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容