博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(转)flutter 新状态管理方案 Provide (一)-使用
阅读量:6127 次
发布时间:2019-06-21

本文共 5095 字,大约阅读时间需要 16 分钟。

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维护起来会稍微省事一些

添加依赖

查看

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(0)));  runApp(    ProviderNode(      child: MyApp(),      providers: providers,    ),  );}

 

 

ProviderNode表示的是提供者

3. 界面/监听

修改_MyHomePageState

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

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

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

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

Provide
( 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
( initialData: _counter, stream: Provide.stream
(context), builder: (BuildContext context, AsyncSnapshot
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
{ Counter get _counter => Provide.value
(context); PageCounter pageCounter = PageCounter(0); PageCounter pageCounter2 = PageCounter(0); var scope1 = ProviderScope("1"); var scope2 = ProviderScope("2"); @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:
[ Text( 'You have pushed the button this many times:', ), Provide
( scope: scope1, builder: (BuildContext context, Widget child, PageCounter counter) { return Text( '${counter.value}', style: Theme.of(context).textTheme.display1, ); }, ), Provide
( scope: scope2, builder: (BuildContext context, Widget child, PageCounter counter) { return Text( '${counter.value}', style: Theme.of(context).textTheme.display1, ); }, ), StreamBuilder
( initialData: _counter, stream: Provide.stream
(context), builder: (BuildContext context, AsyncSnapshot
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
( scope: scope1, builder: (BuildContext context, Widget child, PageCounter counter) {
return Text( '${counter.value}', style: Theme.of(context).textTheme.display1, ); },),

 

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

后记

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

 

转载于:https://www.cnblogs.com/stroll/p/10598670.html

你可能感兴趣的文章
Mindjet MindManager 2019使用教程:
查看>>
游戏设计的基本构成要素有哪些?
查看>>
详解 CSS 绝对定位
查看>>
AOP
查看>>
我的友情链接
查看>>
NGUI Label Color Code
查看>>
.NET Core微服务之基于Polly+AspectCore实现熔断与降级机制
查看>>
vue组件开发练习--焦点图切换
查看>>
浅谈OSI七层模型
查看>>
Webpack 2 中一些常见的优化措施
查看>>
移动端响应式
查看>>
python实现牛顿法求解求解最小值(包括拟牛顿法)【最优化课程笔记】
查看>>
js中var、let、const的区别
查看>>
腾讯云加入LoRa联盟成为发起成员,加速推动物联网到智联网的进化
查看>>
从Python2到Python3:超百万行代码迁移实践
查看>>
Windows Server已可安装Docker,Azure开始支持Mesosphere
查看>>
简洁优雅地实现夜间模式
查看>>
react学习总结
查看>>
微软正式发布PowerShell Core 6.0
查看>>
Amazon发布新的会话管理器
查看>>