flutter 新状态管理方案 Provide (一)-使用

 
 
版权声明:本文为博主原创文章,基于CC4.0协议,首发于https://kikt.top ,同步发于csdn,转载必须注明出处! https://blog.csdn.net/qq_28478281/article/details/87858386

开这篇文章是因为看到这个库被托管在google的仓库下,而且说明是被设计出来替代ScopedModel的,而且更加灵活

支持Builder模式和StreamBuilder模式,全局,局部都可以

内部应该是结合InheritedWidget Notification体系实现的

传统的bloc需要在每一个Repository中创建StreamControllerStream,甚至有的文章中,一个监听的修改需要修改5处,维护起来比较麻烦

相比较而言Provide维护起来会稍微省事一些

入门级仓库地址

添加依赖

查看pub-install

  1. dependencies:
  2. provide: ^1.0.1 # 这里的版本查看官方
 

flutter packages get

  1. import 'package:provide/provide.dart';

使用方法

这里以简单的Counter为例
也就是在flutter的hello world工程的基础上来修改

1. 定义一个Model

这个model需要继承ChangeNotifier

  1. class Counter with ChangeNotifier {
  2. int _value;
  3.  
  4. int get value => _value;
  5.  
  6. Counter(this._value);
  7.  
  8. void inc() {
  9. _value++;
  10. notifyListeners(); //父类的方法,发出通知
  11. }
  12. }
  1.  

2. 定义一个全局的Provide

这里虽然定义在全局,但事实上也可以定义在页面级

  1. void main() {
  2. var providers = Providers()..provide(Provider.function((ctx) => Counter()));
  3.  
  4. runApp(
  5. ProviderNode(
  6. child: MyApp(),
  7. providers: providers,
  8. ),
  9. );
  10. }
 

ProviderNode表示的是提供者

3. 界面/监听

修改_MyHomePageState

添加一个方法,用于获取Counter实例

  1. Counter get _counter => Provide.value<Counter>(context);
 

将原来的Text(_counter)修改一下

这里的Provide会在Counter发生变化的时候,触发builder回调来更新界面

  1. Provide<Counter>(
  2. builder: (BuildContext context, Widget child, Counter counter) {
  3. return Text(
  4. '${counter.value}',
  5. style: Theme.of(context).textTheme.display1,
  6. );
  7. },
  8. ),
 

4. 发出通知

接着就是发出通知了

修改floatingActionButton的点击事件

  1. floatingActionButton: FloatingActionButton(
  2. onPressed: () => _counter.inc(),
  3. tooltip: 'Increment',
  4. child: Icon(Icons.add),
  5. ),
 

这里调用第三步获取的那个Counter,然后调用inc方法


看到这里,如果之前用过ScopedModel的朋友会问了,这个不是和以前一样吗,我为啥要改呢

继续修改

5. Stream模式

这个就很类似于bloc了,只不过model不太一样

添加一个StreamBuilder

  1. StreamBuilder<Counter>(
  2. initialData: _counter,
  3. stream: Provide.stream<Counter>(context),
  4. builder: (BuildContext context, AsyncSnapshot<Counter> snapshot) {
  5. return Text(
  6. '${snapshot.data.value}',
  7. style: Theme.of(context).textTheme.display1,
  8. );
  9. },
  10. ),
 

这里initialData是第三步创建的那个,stream是使用Provide.stream<Counter>(context)获取的

scope

provide中有一个概念叫scope,类的完整类名叫ProviderScope

  1. class ProviderScope {
  2. final String _name;
  3. /// Constructor
  4. const ProviderScope(this._name);
  5. @override
  6. String toString() {
  7. return "Scope ('$_name')";
  8. }
  9. }
 

这个类的作用就是标识Provider的区域,或者可以理解为给Provider/Provide定义一个作用区域

只有scope相同的才可以识别

将state的代码修改一下

  1. class _MyHomePageState extends State<MyHomePage> {
  2. Counter get _counter => Provide.value<Counter>(context);
  3.  
  4. PageCounter pageCounter = PageCounter();
  5. PageCounter pageCounter2 = PageCounter();
  6. var scope1 = ProviderScope("");
  7. var scope2 = ProviderScope("");
  8. @override
  9. Widget build(BuildContext context) {
  10. return ProviderNode(
  11. providers: Providers()
  12. ..provide(Provider.value(pageCounter), scope: scope1)
  13. ..provide(Provider.value(pageCounter2), scope: scope2),
  14. child: Scaffold(
  15. appBar: AppBar(
  16. title: Text(widget.title),
  17. ),
  18. body: Center(
  19. child: Column(
  20. mainAxisAlignment: MainAxisAlignment.center,
  21. children: <Widget>[
  22. Text(
  23. 'You have pushed the button this many times:',
  24. ),
  25. Provide<PageCounter>(
  26. scope: scope1,
  27. builder:
  28. (BuildContext context, Widget child, PageCounter counter) {
  29. return Text(
  30. '${counter.value}',
  31. style: Theme.of(context).textTheme.display1,
  32. );
  33. },
  34. ),
  35. Provide<PageCounter>(
  36. scope: scope2,
  37. builder:
  38. (BuildContext context, Widget child, PageCounter counter) {
  39. return Text(
  40. '${counter.value}',
  41. style: Theme.of(context).textTheme.display1,
  42. );
  43. },
  44. ),
  45. StreamBuilder<Counter>(
  46. initialData: _counter,
  47. stream: Provide.stream<Counter>(context),
  48. builder:
  49. (BuildContext context, AsyncSnapshot<Counter> snapshot) {
  50. return Text(
  51. '${snapshot.data.value}',
  52. style: Theme.of(context).textTheme.display1,
  53. );
  54. },
  55. ),
  56. FlatButton(
  57. child: Text("nextPage"),
  58. onPressed: () {
  59. Navigator.push(context,
  60. MaterialPageRoute(builder: (BuildContext context) {
  61. return MyHomePage(
  62. title: "new page",
  63. );
  64. }));
  65. },
  66. ),
  67. ],
  68. ),
  69. ),
  70. floatingActionButton: FloatingActionButton(
  71. onPressed: () {
  72. _counter.inc();
  73. pageCounter.inc();
  74. pageCounter2.rec();
  75. },
  76. tooltip: 'Increment',
  77. child: Icon(Icons.add),
  78. ),
  79. ),
  80. );
  81. }
  82. }
 

这里定义了两个scope,并在Provide时进行了指定

  1. Provide<PageCounter>(
  2. scope: scope1,
  3. builder:
  4. (BuildContext context, Widget child, PageCounter counter) {
  5. return Text(
  6. '${counter.value}',
  7. style: Theme.of(context).textTheme.display1,
  8. );
  9. },
  10. ),
 

这样只有当对应scope1的counter发出通知时,这里才会回调,这样就满足了一个页面/一个应用中有两个相同对象的识别问题

后记

这个插件托管在google仓库下,个人觉得应该是官方很推荐的一种状态管理模式

(转)flutter 新状态管理方案 Provide (一)-使用的更多相关文章

  1. 为了弄懂Flutter的状态管理, 我用10种方法改造了counter app

    为了弄懂Flutter的状态管理, 我用10种方法改造了counter app 本文通过改造flutter的counter app, 展示不同的状态管理方法的用法. 可以直接去demo地址看代码: h ...

  2. vuex-- Vue.的中心化状态管理方案(vue 组件之间的通信简化机制)

    vuex-- Vue.的中心化状态管理方案(vue 组件之间的通信简化机制) 如果你在使用 vue.js , 那么我想你可能会对 vue 组件之间的通信感到崩溃 .vuex就是为了解决组件通信问题的. ...

  3. 借鉴redux,实现一个react状态管理方案

    react状态管理方案有很多,其中最简单的最常用的是redux. redux实现 redux做状态管理,是利用reducer和action实现的state的更新. 如果想要用redux,需要几个步骤 ...

  4. Redux/Mobx/Akita/Vuex对比 - 选择更适合低代码场景的状态管理方案

    近期准备开发一个数据分析 SDK,定位是作为数据中台向外输出数据分析能力的载体,前端的功能表现类似低代码平台的各种拖拉拽.作为中台能力的载体,SDK 未来很大概率会需要支持多种视图层框架,比如Vue2 ...

  5. Flutter状态管理之provide和provider的使用区别

    说道状态管理不得不说谷歌的亲自开发的两款状态管理Widget:第一个是provide,第二个是provider. 这两个的区别就是一个出来的早,现在好像没整么更新了.第二个是2019才出来的目前的版本 ...

  6. Flutter 对状态管理的认知与思考

    前言 由 编程技术交流圣地[-Flutter群-] 发起的 状态管理研究小组,将就 状态管理 相关话题进行为期 两个月 的讨论. 目前只有内定的 5 个人参与讨论,如果你对 状态管理 有什么独特的见解 ...

  7. Flutter Bloc状态管理 简单上手

    我们都知道,Flutter中Widget的状态控制了UI的更新,比如最常见的StatefulWidget,通过调用setState({})方法来刷新控件.那么其他类型的控件,比如StatelessWi ...

  8. Flutter 状态管理 flutter_Provide

    项目的商品类别页面将大量的出现类和类中间的状态变化,这就需要状态管理.现在Flutter的状态管理方案很多,redux.bloc.state.Provide. Scoped Model : 最早的状态 ...

  9. React状态管理相关

    关于React状态管理的一些想法 我最开始使用React的时候,那个时候版本还比较低(16版本以前),所以状态管理都是靠React自身API去进行管理,但当时最大的问题就是跨组件通信以及状态同步和状态 ...

随机推荐

  1. Python3的List操作和方法

    列表函数: len(list):列表元素个数 max(list):返回list中最大的元素 min(list):返回list中最小的元素 list(seq):将元组转换为列表 列表方法: list.a ...

  2. IO文件流

    定义:流是一种抽象的概念,通过流的方式组成无结构字符和字符序列,从流中取数据的操作进行输入输出.[io流的作用就是用流的方式进行输入输出] 常用语法: 1.   首先引用using.system.io ...

  3. response响应

    郭晨 软件151 1531610114 response1.response常用APIsetStatus:设置响应行当中的状态码setHeader:设置响应头信息getOutputStream:获得字 ...

  4. cookie 就是一些字符串信息

    什么是 Cookie “cookie 是存储于访问者的计算机中的变量.每当同一台计算机通过浏览器请求某个页面时,就会发送这个 cookie.你可以使用JavaScript 来创建和取回cookie 的 ...

  5. Android与Linux内核的对应关系

    1. Android各版本和Linux版本对应关系 Android Version |API Level |Linux Kernel in AOSP ------------------------- ...

  6. Mxd文档更新比例尺

    在AE中,更新Mxd文档的比例尺,比较特殊.写代码以记录,更新比例尺代码如图所示: [DllImport("User32.dll")] public static extern i ...

  7. Linux上静态库和动态库的编译和使用

    linux上静态库和动态库的编译和使用(附外部符号错误浅谈) 这就是静态库和动态库的显著区别,静态库是编译期间由链接器通过include目录找到并链接到到可执行文件中,而动态库则是运行期间动态调用,只 ...

  8. 转发 Delphi中线程类TThread 实现多线程编程

    Delphi中有一个线程类TThread是用来实现多线程编程的,这个绝大多数Delphi书藉都有说到,但基本上都是对TThread类的几个成员作一简单介绍,再说明一下Execute的实现和Synchr ...

  9. Python基础之条件语句和循环

    条件语句 Python中的条件语句分为 if ...else . if ...elif...else  以及if ...else 的嵌套使用: username = input('请输入您的用户名:' ...

  10. 刘志梅2017710101152.《面向对象程序设计(java)》第十三周学习总结

    实验十三  图形界面事件处理技术 实验时间 2018-11-22 1.理论知识 (1)任何支持GUI的操作环境都要不断地监视按键或点击鼠标这样的事件. JAVA这样的面向对象语言,都将事件的相关的信息 ...