使用Provider對Flutter應用進行狀態管理

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 創建並初始化即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章