| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 移动开发 -> 为了弄懂Flutter的状态管理 我用10种方法改造了counter app -> 正文阅读 |
|
[移动开发]为了弄懂Flutter的状态管理 我用10种方法改造了counter app |
import ‘package:scoped_model/scoped_model.dart’; class CounterModel extends Model { int _counter = 0; int get counter => _counter; void increment() { _counter++; notifyListeners(); } void decrement() { _counter–; notifyListeners(); } } 其中数据变化的部分会通知listeners, 它们收到通知后会rebuild. 在上层初始化并提供数据类, 用 访问数据有两种方法:
使用的时候注意要提供泛型类型, 会帮助我们找到离得最近的上层 ScopedModelDescendant( builder: (context, child, model) { return Text( model.counter.toString(), ); }), 数据改变后, 只有
对于button来说, 它只是控制改变, 自身并不需要重绘, 可以把这个属性置为false. ScopedModelDescendant( rebuildOnChange: false, builder: (context, child, model) { return FloatingActionButton( onPressed: model.increment, tooltip: ‘Increment’, child: Icon(Icons.add), ); }, ), scoped model这个库帮我们解决了数据访问和通知的问题, 但是rebuild范围需要自己控制.
代码分支: scoped-model Provider Provider是官方文档的例子用的方法. 去年的Google I/O 2019也推荐了这个方法. 和BLoC的流式思想相比, Provider是一个观察者模式, 状态改变时要 有一个counter版本的sample: https://github.com/flutter/samples/tree/master/provider_counter Provider的实现在内部还是利用了 Provider的好处: dispose指定后会自动被调用, 支持 Provider实现
class CounterModel extends ChangeNotifier { int value = 0; void increment() { value++; notifyListeners(); } void decrement() { value–; notifyListeners(); } }
void main() => runApp(ChangeNotifierProvider( create: (context) => CounterModel(), child: MyApp(), ));
Consumer( builder: (context, counter, child) => Text( ‘${counter.value}’, ), ), FAB: FloatingActionButton( onPressed: () => Provider.of(context, listen: false).increment(), ), 这里 Provider性能相关的实现细节
可以用于缓存一些并不需要重建的widget: return Consumer( builder: (context, cart, child) => Stack( children: [ // Use SomeExpensiveWidget here, without rebuilding every time. child, Text(“Total price: ${cart.totalPrice}”), ], ), // Build the expensive widget here. child: SomeExpensiveWidget(), ); 代码分支: provider. BLoC BLoC模式的全称是: business logic component. 所有的交互都是a stream of asynchronous events.
BLoC的实现的主要思路: Events in -> BloC -> State out. Google I/O 2018上推荐的还是这个, 2019就推荐Provider了. 当然也不是说这个模式不好, 架构模式本来也没有对错之分, 只是技术选型不同. BLoC手动实现不添加任何依赖可以手动实现BLoC, 利用:
可以有多个stream, UI只在自己感兴趣的信息发生变化的时候重建. BLoC中:
CounterBloc类: class CounterBloc { int _counter = 0; final _counterStateController = StreamController(); StreamSink get _inCounter => _counterStateController.sink; Stream get counter => _counterStateController.stream; final _counterEventController = StreamController(); Sink get counterEventSink => _counterEventController.sink; CounterBloc() { _counterEventController.stream.listen(_mapEventToState); } void _mapEventToState(CounterEvent event) { if (event is IncrementEvent) { _counter++; } else if (event is DecrementEvent) { _counter–; } _inCounter.add(_counter); } void dispose() { _counterStateController.close(); _counterEventController.close(); } } 有两个 读取状态值要用 StreamBuilder( stream: _bloc.counter, initialData: 0, builder: (BuildContext context, AsyncSnapshot snapshot) { return Text( ‘${snapshot.data}’, ); }, ) 而改变状态是发送事件: FloatingActionButton( onPressed: () => _bloc.counterEventSink.add(IncrementEvent()), ), 实现细节:
代码分支: bloc BLoC传递: 用InheritedWidget手动实现的BLoC模式, 可以结合 代码分支: bloc-with-provider BLoC rxdart实现用了rxdart package之后, bloc模块的实现可以这样写: class CounterBloc { int _counter = 0; final _counterSubject = BehaviorSubject(); Stream get counter => _counterSubject.stream; final _counterEventController = StreamController(); Sink get counterEventSink => _counterEventController.sink; CounterBloc() { _counterEventController.stream.listen(_mapEventToState); } void _mapEventToState(CounterEvent event) { if (event is IncrementEvent) { _counter++; } else if (event is DecrementEvent) { _counter–; } _counterSubject.add(_counter); } void dispose() { _counterSubject.close(); _counterEventController.close(); } }
代码分支: bloc-rxdart. BLoC Library可以用这个package来帮我们简化代码: https://pub.dev/packages/flutter_bloc 自己只需要定义Event和State的类型并传入, 再写一个逻辑转化的方法: class CounterBloc extends Bloc<CounterEvent, CounterState> { @override CounterState get initialState => CounterState.initial(); @override Stream mapEventToState(CounterEvent event) async* { if (event is IncrementEvent) { yield CounterState(counter: state.counter + 1); } else if (event is DecrementEvent) { yield CounterState(counter: state.counter - 1); } } } 用 访问的时候用 BlocBuilder( bloc: BlocProvider.of(context), builder: (BuildContext context, CounterState state) { return Text( ‘${state.counter}’, ); }, ), 这里bloc参数如果没有指定, 会自动向上寻找.
FloatingActionButton( onPressed: () => BlocProvider.of(context).add(IncrementEvent()), ), 代码分支: bloc-library. rxdart 这是个原始版本的流式处理. 和BLoC相比, 没有专门的逻辑模块, 只是改变了数据的形式. 利用rxdart, 把数据做成流: class CounterModel { BehaviorSubject _counter = BehaviorSubject.seeded(0); get stream$ => _counter.stream; int get current => _counter.value; increment() { _counter.add(current + 1); } decrement() { _counter.add(current - 1); } } 获取数据用 StreamBuilder( stream: counterModel.stream$, builder: (BuildContext context, AsyncSnapshot snapshot) { return Text( ‘${snapshot.data}’, ); }, ), Widget dispose的时候会自动解绑. 数据传递的部分还需要进一步处理. 代码分支: rxdart. Redux Redux是前端流行的, 一种单向数据流架构. 概念:
Flutter Redux状态管理实现首先定义好action, state: enum Actions { Increment, Decrement, } class CounterState { int _counter; int get counter => _counter; CounterState(this._counter); } reducer方法根据action和当前state产生新的state: CounterState reducer(CounterState prev, dynamic action) { if (action == Actions.Increment) { return new CounterState(prev.counter + 1); } else if (action == Actions.Decrement) { return new CounterState(prev.counter - 1); } else { return prev; } }
放在上层: StoreProvider( store: store, child: MaterialApp( title: ‘Flutter Demo’, theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(title: ‘Flutter Demo Home Page’), ), );
读状态: StoreConnector<CounterState, String>( converter: (store) => store.state.counter.toString(), builder: (context, count) { return ‘$count’, ); }, ) 改变状态: 发送action: StoreConnector<CounterState, VoidCallback>( converter: (store) { return () => store.dispatch(action.Actions.Increment); }, builder: (context, callback) { return FloatingActionButton( onPressed: callback, ); }, ), 代码分支: redux. MobX MobX本来是一个JavaScript的状态管理库, 它迁移到dart的版本: mobxjs/mobx.dart. 核心概念:
MobX状态管理实现官网提供了一个counter的指导: https://mobx.netlify.com/getting-started 这个库的实现需要先生成一些代码. 先写类: import ‘package:mobx/mobx.dart’; part ‘counter.g.dart’; class Counter = _Counter with _$Counter; abstract class _Counter with Store { @observable int value = 0; @action void increment() { value++; } @action void decrement() { => store.state.counter.toString(), builder: (context, count) { return [外链图片转存中…(img-8RIN0tAq-1642929754290)] ‘$count’, ); }, ) 改变状态: 发送action: StoreConnector<CounterState, VoidCallback>( converter: (store) { return () => store.dispatch(action.Actions.Increment); }, builder: (context, callback) { return FloatingActionButton( onPressed: callback, ); }, ), 代码分支: redux. MobX MobX本来是一个JavaScript的状态管理库, 它迁移到dart的版本: mobxjs/mobx.dart. 核心概念:
MobX状态管理实现官网提供了一个counter的指导: https://mobx.netlify.com/getting-started 这个库的实现需要先生成一些代码. 先写类: import ‘package:mobx/mobx.dart’; part ‘counter.g.dart’; class Counter = _Counter with _$Counter; abstract class _Counter with Store { @observable int value = 0; @action void increment() { value++; } @action void decrement() { |
|
移动开发 最新文章 |
Vue3装载axios和element-ui |
android adb cmd |
【xcode】Xcode常用快捷键与技巧 |
Android开发中的线程池使用 |
Java 和 Android 的 Base64 |
Android 测试文字编码格式 |
微信小程序支付 |
安卓权限记录 |
知乎之自动养号 |
【Android Jetpack】DataStore |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 13:01:21- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |