inheritedWidget是如何實現(xiàn)數(shù)據(jù)共享的?
要解決這個問題,首先我們先看下,這個數(shù)據(jù)是如何存取的,又是如何刷新的.
一. _inheritedWidgets的存取
這個問題的奧秘其實就在Element中.
我們先來看一下inheritedWidget數(shù)據(jù)共享使用過程中的這個Map存取:
取:
通常我們使用inheritedWidget的時候,都是會有一個取數(shù)據(jù)的過程,這個時候我們會通過子節(jié)點的BuildContext(Element是BuildContext的實現(xiàn)類,使用context.getElementForInheritedWidgetOfExactType() 或 context.dependOnInheritedWidgetOfExactType來獲取到這個widget或element從而獲取到數(shù)據(jù)(例如上次講的例子).
查看這兩個方法,在Element中,都是從 _inheritedWidgets這個map里取值绽乔,泛型T是key
存:
InhertiedElement中重寫了這個_updateInheritance()方法:
若父節(jié)點的_inheritedWidgets不為空,將其深拷貝給子節(jié)點的_inheritedWidgets;
若父節(jié)點的_inheritedWidgets為空,初始化一個Map,key為其widget的runtimeType
我們可以看到,element中有Map<Type, InheritedElement>? _inheritedWidgets成員變量,這個成員變量一般情況下是空的,只有當(dāng)父控件或本身是InheritedWidget的時候, _inheritedWidgets才會被初始化.
當(dāng)父控件是InheritedWidget是,這個Map會在Element中被一級一級的向下傳遞與合并.
二. dependOnInheritedWidgetOfExactType方法中到底做了什么
通過element中對此方法的描述及InheritedElement中此方法的實現(xiàn),可以看出:
- 1. 從_inheritedWidgets中查找是否有該類型的InheritedElement
-
2. 查找到有的話,執(zhí)行dependOnInheritedElement方法,將它添加到_dependencies里面; 并且調(diào)用ancestor.updateDependencies(this, aspect), 將當(dāng)前Element添加到_dependents(Map<Element, Object?> _dependents)里面
- 3.返回這個element對應(yīng)的widget (dependOnInheritedElement方法中)
三. getElementForInheritedWidgetOfExactType與dependOnInheritedWidgetOfExactType的區(qū)別
通過上圖我們也可以看出, 兩個方法的主要區(qū)別在于, getElementForInheritedWidgetOfExactType是直接獲取了_inheritedWidgets內(nèi)的InheritedElement返回;而dependOnInheritedWidgetOfExactType在獲取的過程中,還多做了一步_dependents的管理,將_inheritedWidgets中的依賴關(guān)系管理起來
當(dāng)inheritedWidget被更新時, _dependents中的element會被逐個執(zhí)行notifyDependent,最后觸發(fā)markNeedsBuild進(jìn)行重繪.
當(dāng)執(zhí)行notifyDependent時,會觸發(fā)Element的didChangeDependencies方法,將_didChangeDependencies置為true,從而觸發(fā)State的didChangeDependencies的回調(diào)生命周期
總結(jié)
所以,當(dāng)我們inheritedWidget來實現(xiàn)數(shù)據(jù)共享的時候,需要注意兩個點
- 1.使用的context,必須是inheritedWidget的child widget對應(yīng)的context---(Element)
- 2.getElementForInheritedWidgetOfExactType和dependOnInheritedWidgetOfExactType的區(qū)別