inheritedWidget是如何實(shí)現(xiàn)數(shù)據(jù)共享的?
要解決這個(gè)問(wèn)題,首先我們先看下,這個(gè)數(shù)據(jù)是如何存取的,又是如何刷新的.
一. _inheritedWidgets的存取
這個(gè)問(wèn)題的奧秘其實(shí)就在Element中.

我們先來(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ù)(例如上次講的例子).

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

存:

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

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

二. 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ū)別

通過(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)行重繪.



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


總結(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ū)別



