前言:不同狀態(tài)管理框架的解決思路不一樣,從實現(xiàn)上可以分為兩大類:
- 通過 Flutter 樹機制 解決,例如 Provider糯俗;
- 通過 依賴注入顶霞,例如 Get肄程。
名稱 | 基本原理 |
---|---|
Provide |
依賴樹機制,必須基于 context选浑,提供了子組件訪問上層的能力 |
Get |
全局單例蓝厌,任意位置可以存取存在類型重復,內(nèi)存回收問題 |
一古徒、Provide
基本原理:Flutter 在 BuildContext 類中為我們提供了方法進行向上和向下的查找拓提,provider 正是借助這種樹機制,完成了 View -> Presenter (控制器)的獲取隧膘。所以每次用 Provider 的時候你都會調(diào)用 Provider.of<T>(context)代态。顯然,所有 Provider 以下的 Widget 節(jié)點疹吃,都可以通過自身的 context 訪問到 Provider 中的 Presenter蹦疑,這很好的解決了跨組件的通信問題。
Provider詳細分析傳送門
二萨驶、Get
1歉摧、原理分析
樹機制很不錯,但他依賴于 context,如果層級比較多叁温,會很讓人抓狂再悼。get 通過依賴注入的方式,實現(xiàn)了對 Presenter(控制器) 層的獲取券盅。簡單來說帮哈,就是將 Presenter 存到一個單例的 Map 中,這樣的好處就是在任何地方都可以獲取到锰镀,十分的靈活方便娘侍,省去了Provide繁雜的中間層處理。
2泳炉、單利遇到的問題
全局單例存儲一定要考慮到 Presenter 的回收憾筏,不然很有可能引起內(nèi)存泄漏。使用 get 要么你手動在頁面 dispose 的時候做 delete 操作花鹅,要么你使用 GetBuilder 氧腰,其實它里面也是在 dispose 去做了釋放。一般情況下刨肃,我們會使用GetBuilder古拴。
@override
void dispose() {
super.dispose();
if (widget.autoRemove && GetInstance().isRegistered<T>(tag: widget.tag)) {
// 移除 Presenter 實例
GetInstance().delete<T>(tag: widget.tag);
}
}
3、為什么使用 Provider 的時候不需要考慮這個問題真友?
重點:這是因為一般頁面級別的 Provider 總是跟隨 PageRoute黄痪。隨著頁面的退出,整樹中的節(jié)點都被會回收盔然,所以可以理解為系統(tǒng)機制為我們解決了這個問題桅打。
4、Get相對Provider的優(yōu)勢
4.1 Provider 中我們通過 context實現(xiàn)跨組件訪問數(shù)據(jù)愈案,Provider要想實現(xiàn)跨頁面訪問那么 Provider 的存儲節(jié)點需要放在一個更高的位置挺尾,但同樣需要注意回收的處理。
4.2 Get 因為是全局單例站绪,無論是跨頁面或者跨組件遭铺,都沒有任何依賴。所以崇众,Get的使用更加快捷掂僵、方便。所以顷歌,在多個跨組件業(yè)務中更加推薦使用Get锰蓬,擺脫Provider的context依賴。
5眯漩、控制刷新范圍
5.1 get 的 Obx 組件使用極為方便簡潔芹扭,調(diào)用如下:
class Home extends StatelessWidget {
var count = 0.obs;
@override
Widget build(context) => Scaffold(
body: Center(
child: Obx(() => Text("$count")),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () => count ++,
));
}
5.2 分析起來就三步
/// 申明變量麻顶,進行obs監(jiān)聽
var count = 0.obs;
/// 響應組件
Obx(() => Text("$count"))
/// 變量修改,同步 Obx 變化
count ++
6舱卡、為什么obs能監(jiān)聽到改變
原因就是obs 這個擴展方法會返回一個 RxInt 類型的對象辅肾,這種對象核心在于他的 get 和 set 方法。內(nèi)部添加了監(jiān)聽addListener轮锥,所以能隨時監(jiān)聽到數(shù)據(jù)的改變矫钓。