美文网首页
Flutter学习之Provider状态管理

Flutter学习之Provider状态管理

作者: 小学生课代表 | 来源:发表于2020-05-08 21:51 被阅读0次
class CounterModel with ChangeNotifier {
  int _count = 0;
  int get value => _count;

  void increment() {
    _count++;
    notifyListeners();
  }
}

void main() {
  final counter = CounterModel();

  runApp(
    ChangeNotifierProvider.value(
        value: counter,
        child: MaterialApp(
          home:FirstScreen()
        ),
      ),
  );
}
class FirstScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final _counter = Provider.of<CounterModel>(context);
    final textSize = Provider.of<int>(context).toDouble();

    return Scaffold(
      appBar: AppBar(
        title: Text('FirstPage'),
      ),
      body: Center(
        child: Text(
          'Value: ${_counter.value}',
          style: TextStyle(fontSize: textSize),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _counter.increment,
        child: Icon(Icons.navigate_next),
      ),
    );
  }

如果你提供了多个状态可以使用MultiProvider

void main() {
  final counter = CounterModel();
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (context)=>Counter()),
      ],
      child: MaterialApp(
          home:FirstScreen()
        ),
      ),
  );
}

定义一个CounterModel,通过Provider组件注入组件树,子组件在build时可以通过Provider.of<CounterModel>(context)获取model,可以从model中获取数据,也可以直接调用model的方法(CounterModel.increment)修改数据。

这里用到的是ChangeNotifierProvider,它也是我们最常用的Provider。

除了ChangeNotifierProvider之外,Provider还提供了另外几种方式进行数据管理:

  1. Provider

    • 单纯共享数据给子组件,但是数据更新时不会通知子组件。
  2. ListenableProvider

    • 比起ChangeNotifierProvider区别主要是不会自动调用ChangeNotifier.dispose释放资源。一般不用。
  3. ValueListenableProvider

    • 可以认为是ChangeNotifierProvider的特例,只监听一个数据的时候,使用ValueListenableProvider在修改数据时可以不用调用notifyListeners()
  4. StreamProvider

    • 用于监听一个Stream
  5. FutureProvider

    • 提供了一个 Future 给其子孙节点,并在 Future 完成时,通知依赖的子孙节点进行刷新

参考链接:https://segmentfault.com/a/1190000021157210?utm_source=tag-newest

Consumer

我们先看 floatingActionButton,使用了一个 Consumer 的情况。

Consumer 使用了 Builder模式,收到更新通知就会通过 builder 重新构建。Consumer<T> 代表了它要获取哪一个祖先中的 Model。

Consumer 的 builder 实际上就是一个 Function,它接收三个参数 (BuildContext context, T model, Widget child)。

context: context 就是 build 方法传进来的 BuildContext 。
T:T也很简单,就是获取到的最近一个祖先节点中的数据模型。
child:它用来构建那些与 Model 无关的部分,在多次运行 builder 中,child 不会进行重建。
然后它会返回一个通过这三个参数映射的 Widget 用于构建自身。

在这个浮动按钮的例子中,我们通过 Consumer 获取到了顶层的 CounterModel 实例。并在浮动按钮 onTap 的 callback 中调用其 increment 方法。

而且我们成功抽离出 Consumer 中不变的部分,也就是浮动按钮中心的 Icon 并将其作为 child 参数传入 builder 方法中。

还有 Consumer2, Consumer3,Consumer4,……

区别

我们来看 Consumer 的内部实现。

@override
  Widget build(BuildContext context) {
    return builder(
      context,
      Provider.of<T>(context),
      child,
    );
  }

可以发现,Consumer 就是通过 Provider.of<T>(context) 来实现的。但是从实现来讲 Provider.of<T>(context) 比 Consumer 简单好用太多,为啥我要搞得那么复杂捏。

实际上 Consumer 非常有用,它的经典之处在于能够在复杂项目中,极大地缩小你的控件刷新范围。Provider.of<T>(context) 将会把调用了该方法的 context 作为听众,并在 notifyListeners 的时候通知其刷新。

class FirstScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Consumer<CounterProvider>(builder: (context, counterModel, child) {
      return Scaffold(
        appBar: AppBar(
          title: Text('FirstPage'),
        ),
        body: Center(
          child: Text(
            'Value: ${counterModel.value}',
          ),
        ),
        floatingActionButton: FloatingActionButon(
          onPressed: counterModel.increment,
          child: Icon(Icons.navigate_next),
        ),
      );
    });
  }
}

原文链接:https://blog.csdn.net/lpfasd123/java/article/details/101573980

相关文章

网友评论

      本文标题:Flutter学习之Provider状态管理

      本文链接:https://www.haomeiwen.com/subject/yhxcnhtx.html