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

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

flutter packages get

import 'package:provide/provide.dart';

使用方法

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

1. 定义一个Model

这个model需要继承ChangeNotifier

class Counter with ChangeNotifier {
int _value; int get value => _value; Counter(this._value); void inc() {
_value++;
notifyListeners(); //父类的方法,发出通知
}
}

2. 定义一个全局的Provide

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

void main() {
var providers = Providers()..provide(Provider.function((ctx) => Counter())); runApp(
ProviderNode(
child: MyApp(),
providers: providers,
),
);
}
 

ProviderNode表示的是提供者

3. 界面/监听

修改_MyHomePageState

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

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

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

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

Provide<Counter>(
builder: (BuildContext context, Widget child, Counter counter) {
return Text(
'${counter.value}',
style: Theme.of(context).textTheme.display1,
);
},
),
 

4. 发出通知

接着就是发出通知了

修改floatingActionButton的点击事件

floatingActionButton: FloatingActionButton(
onPressed: () => _counter.inc(),
tooltip: 'Increment',
child: Icon(Icons.add),
),
 

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


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

继续修改

5. Stream模式

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

添加一个StreamBuilder

StreamBuilder<Counter>(
initialData: _counter,
stream: Provide.stream<Counter>(context),
builder: (BuildContext context, AsyncSnapshot<Counter> snapshot) {
return Text(
'${snapshot.data.value}',
style: Theme.of(context).textTheme.display1,
);
},
),
 

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

scope

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

class ProviderScope {
final String _name; /// Constructor
const ProviderScope(this._name); @override
String toString() {
return "Scope ('$_name')";
}
}
 

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

只有scope相同的才可以识别

将state的代码修改一下

class _MyHomePageState extends State<MyHomePage> {
Counter get _counter => Provide.value<Counter>(context); PageCounter pageCounter = PageCounter();
PageCounter pageCounter2 = PageCounter();
var scope1 = ProviderScope("");
var scope2 = ProviderScope("");
@override
Widget build(BuildContext context) {
return ProviderNode(
providers: Providers()
..provide(Provider.value(pageCounter), scope: scope1)
..provide(Provider.value(pageCounter2), scope: scope2),
child: Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Provide<PageCounter>(
scope: scope1,
builder:
(BuildContext context, Widget child, PageCounter counter) {
return Text(
'${counter.value}',
style: Theme.of(context).textTheme.display1,
);
},
),
Provide<PageCounter>(
scope: scope2,
builder:
(BuildContext context, Widget child, PageCounter counter) {
return Text(
'${counter.value}',
style: Theme.of(context).textTheme.display1,
);
},
),
StreamBuilder<Counter>(
initialData: _counter,
stream: Provide.stream<Counter>(context),
builder:
(BuildContext context, AsyncSnapshot<Counter> snapshot) {
return Text(
'${snapshot.data.value}',
style: Theme.of(context).textTheme.display1,
);
},
),
FlatButton(
child: Text("nextPage"),
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (BuildContext context) {
return MyHomePage(
title: "new page",
);
}));
},
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
_counter.inc();
pageCounter.inc();
pageCounter2.rec();
},
tooltip: 'Increment',
child: Icon(Icons.add),
),
),
);
}
}
 

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

Provide<PageCounter>(
scope: scope1,
builder:
(BuildContext context, Widget child, PageCounter counter) {
return Text(
'${counter.value}',
style: Theme.of(context).textTheme.display1,
);
},
),
 

这样只有当对应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. 树的子结构(JAVA)

    树的子结构 题目描述 输入两棵二叉树A,B,判断B是不是A的子结构.(ps:我们约定空树不是任意一个树的子结构) public boolean HasSubtree(TreeNode root1, T ...

  2. c#实现识别图片上的验证码数字

    这篇文章主要介绍了c#实现识别图片上的验证码数字的方法,本文给大家汇总了2种方法,有需要的小伙伴可以参考下. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 1 ...

  3. 新手入门HTML5有什么推荐的书籍?

    很多想迈入HTML5开发行列的人,都会问一个问题:要成为一个更好的开发人员,我应该读哪些书?有哪些HTML5开发的书籍推荐吗? 有人说开卷有益,读万卷书行万里路;有人说,书不在多,精益求精;有人说,书 ...

  4. java8_api_io

    IO-1    i/o的概念    File类详解        java.io.File    java.io.FileFilter接口        只有一个方法        这是一个函数式接口 ...

  5. 在kerberos认证过程中Active Directory的作用

    LDAP介绍 1),ladp(Lightweight Directory Access Protocol),轻量级目录访问协议,提供被称为目录服务的信息服务,特别是基于X.500(构成全球分布式的目录 ...

  6. 学习3DES加密算法笔记

    3DES(或称为Triple DES)是三重数据加密算法(TDEA,Triple Data Encryption Algorithm)块密码的通称.它相当于是对每个数据块应用三次DES加密算法.由于计 ...

  7. 2018-2019-2 20165308网络对抗技术 Exp6:信息收集与漏洞扫描

    2018-2019-2 20165308网络对抗技术 Exp6:信息收集与漏洞扫描 实践目标 掌握信息搜集的最基础技能与常用工具的使用方法. 实践内容 (1)各种搜索技巧的应用 (2)DNS IP注册 ...

  8. javascript中的立即执行函数的原理

    形如 ((function Test(a) { //code here... })('Hello')); 被称作立即执行函数. 首先需要了解的是,这并不是一种hack,这是javascript的基本语 ...

  9. Redis入门的简单使用

    Redis是什么? redis是一个开源的,面向键/值对的NOSQL的分布式数据库系统 NOSQL指的是非关系型的数据,简单直白地讲就是在非关系型的数据库中不存在表的概念,而是以键值对的方式, 即一个 ...

  10. php验证地图坐标在某片坐标区域内

    mysql空间查询并不太适合地图坐标,如果使用:http://www.cnblogs.com/tyjsjl/p/8760002.html的方式进行地图点坐标的查询就不好用了,于是直接使用php来进行地 ...