使用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 创建并初始化即可。

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