Demo
創建共享數據類
import 'package:flutter/material.dart';
///數據 Model
/// Model 實際上就是我們的狀態,
/// 它不僅儲存了我們的數據模型,而且還包含了更改數據的方法,並暴露出它想要暴露出的數據。
/// ChangeNotifier這個類能夠幫駐我們自動管理所有聽衆
/// 調用 notifyListeners() 時,它會通知所有聽衆進行刷新。
class Counter with ChangeNotifier {
///改變的變量
int _value = 0;
int get value =>_value;//將——value暴露出去
///增加邏輯
add(){
_value++;
notifyListeners();//通知引用變量的地方改變值/// //父類的方法,發出通知
}
///減少邏輯
subtract(){
_value--;
notifyListeners();
}
}
訪問數據
Provider 獲取數據狀態有兩種方式:
使用 Provider.of<T>(context)//導致調用的 context 頁面範圍的刷新
使用 Consumer//刷新了 Consumer 的部分
不過這兩種方式都需要在頂層套上 ChangeNotifierProvider():
區別:
Consumer 就是通過 Provider.of<T>(context) 來實現的
實際上 Consumer 非常有用,它的經典之處在於能夠在複雜項目中,極大地縮小你的控件刷新範圍。
Provider.of<T>(context) 將會把調用了該方法的 context 作爲聽衆,並在 notifyListeners的時候通知其刷新。
使用Consumer -局部刷新而不是整個頁面
直接用 Consumer 包住需要使用共享數據的 Widget,同樣的,Consumer 也要指明類型。
建議各位儘量使用 Consumer 而不是 Provider.of<T>(context) 獲取頂層數據
return Container(
child: Consumer<Counter>(
builder: (context, Counter counter, _) =>
///三個參數:(BuildContext context, T model, Widget child)
///context: context 就是 build 方法傳進來的 BuildContext 在這裏就不細說了
///T:獲取到的最近一個祖先節點中的數據模型。
///child:它用來構建那些與 Model 無關的部分,在多次運行 builder 中,child 不會進行重建
///=>返回一個通過這三個參數映射的 Widget 用於構建自身
Center(
child: Column(
children: <Widget>[
Text(counter.value.toString()),
RaisedButton(child: Text("增加"), onPressed: () => counter.add()),
RaisedButton(child: Text("減少"), onPressed: () => counter.subtract())
],
)
),
)
);
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
var dataInfo = Provider.of<DataInfo>(context);
return MaterialApp(
home: MyHomePage(),
theme: dataInfo.themeData,
);
}
}
通過Provider.of<DataInfo>(context) 獲取 DataInfo 實例,需要在 of 函數後指明具體的數據類。然後就可以直接通過 getter 訪問到 themeData 了
使用Multiprovider管理多個共享數據類
數據類
在應用頂層放置MultiProvider
var counter = Counter();///引用model類
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider.value(value: counter)
],
child:MyApp(),
)
);
關於原則
1.不要所有狀態都放在全局,嚴格區分你的全局數據與局部數據,資源不用了就要釋放!
2.儘量在 Model 中使用私有變量"_"
3.控制刷新範圍:組合大於繼承的特性隨處可見。常見的 Widget 實際上都是由更小的 Widget 組合而成,直到基本組件爲止。爲了使我們的應用擁有更高的性能,控制 Widget 的刷新範圍便顯得至關重要。
相關問題
Provider是如何做到狀態共享的
1.獲取頂層數據
2.通知刷新:使用了 Listener 模式。Model 中維護了一堆聽衆,然後 notifiedListener 通知刷新。(空間換時間)
應該在哪裏進行數據初始化
1.全局數據
當我們需要獲取全局頂層數據並需要做一些會產生額外結果的時候,main 函數是一個很好的選擇。
我們可以在 main 方法中創建 Model 並進行初始化的工作,這樣就只會執行一次。
2.單頁面
頁面級別的 Model 數據都在頁面頂層 Widget 創建並初始化即可。