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. zabbix使用邮箱告警

    目的:使用自己的邮箱(目前我使用的是腾讯企业邮箱)发送告警邮件 1.配置Email:管理->报警媒介类型->Email->修改对应Email参数 2.修改admin用户的报警媒介Em ...

  2. Beginning Math and Physics For Game Programmers (Wendy Stahler 著)

    Chapter 1. Points and Lines (已看) Chapter 2. Geometry Snippets (已看) Chapter 3. Trigonometry Snippets  ...

  3. 通过ZipKin整理调用链路

    缘由 公司使用的是Docker+微服务,服务拆分差不多41个了,然后过完年来就接到这个需求,把指定业务功能的业务基线整理出来,比如,登录这个操作会经过哪些微服务,把登录这个操作的链条列出来,从api- ...

  4. C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V120\Microsoft.CppBuild.targets(388,5): warning MSB8028: The intermediate directory (Debug) contains files shared from another project (GU.vcxproj). T

    1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V120\Microsoft.CppBuild.targets(388,5): warni ...

  5. 一台电脑支持2个git账号:gitlab+github

    一.背景 1.公司使用gitlab保存代码,git已支持. 2.需要新增一个人github账户.创建study项目并提交到github上. 3.git提交时互相不混淆 二.操作流程 1.注册githu ...

  6. .NET MVC 表主外键关系 JSON 无限循环 方案二(推荐)

    public class JsonResultObject:JsonResult { private Newtonsoft.Json.JsonSerializerSettings Settings { ...

  7. C# Json 和对象的相互转换

    Json 和对象的相互转换 /// <summary> /// Json 和对象的相互转换 ——需引用using Newtonsoft.Json; 即:Jsonnet.net..... / ...

  8. final link failed: Nonrepresentable section on output

    编译live555的时候遇到了这个问题,前面的编译没有问题,是在链接的时候出现的,在网上搜索说是缺少 libstdc++ 库.于是,安装之 #sudo apt-get install  libstdc ...

  9. (转)Android之发送短信的两种方式

    https://www.cnblogs.com/dongweiq/p/4866022.html if(TextUtils.isEmpty(number)||TextUtils.isEmpty(cont ...

  10. 爬虫系列2:Requests+Xpath 爬取租房网站信息

    Requests+Xpath 爬取租房网站信息 [抓取]:参考前文 爬虫系列1:https://www.cnblogs.com/yizhiamumu/p/9451093.html [分页]:参考前文 ...