Flutter 状态管理- 使用 MobX

文 / Paul Halliday, developer.school 创始人
众所周知,状态管理是每个软件项目都需要持续迭代更新的方向。它并不是一个「一次性」的工作,
而需要不断确保你遵循的最佳实践能够让你的工程保持良好的可维护性。
要在 Flutter 中高效地使用 MobX ,需要遵循以下原则:
- 我们能访问任意状态中的可观察对象(即在我们应用运行过程中发生变化的变量)。
- 我们可以在 View 中展示这些状态,并响应 Action 意图。
- 我们可以修改状态,从而更新可观察对象以及相应的 View。
那么它的优势在哪呢?答案是,通过 MobX 完成这一切将会变得超级简单!codegen 工具可以帮我们完成绝大部分模版化的工作。
初始化项目
让我们从创建一个全新的 Flutter 工程开始吧:
# New Flutter project
$ flutter create f_mobx && cd f_mobx
# Open in VS Code
$ code .
下一步,我们得在 pubspec.yaml 中拉取一些依赖 (dependencies 与 dev_dependencies):
dependencies:
flutter:
sdk: flutter
mobx:
flutter_mobx:
dev_dependencies:
flutter_test:
sdk: flutter
build_runner: ^1.3.1
mobx_codegen:
之后我们可以在 main.dart 中创建一个全新的 MaterialApp 以放置我们的 CounterPage。
import 'package:f_mobx/pages/counter_page.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: CounterPage(),
);
}
}
下一步,我们需要在 lib/pages/counter_page.dart 中创建 CounterPage,并完成用户界面的构建。其中包括了一个增加按钮和一个减少按钮。
import 'package:flutter/material.dart';
class CounterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text('Flutter and MobX'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Counter',
style: TextStyle(fontSize: 30.0),
),
Text(
'0',
style: TextStyle(fontSize: 42.0),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FlatButton.icon(
icon: Icon(Icons.add),
label: Text('Add'),
onPressed: () {},
),
FlatButton.icon(
icon: Icon(Icons.remove),
label: Text('Remove'),
onPressed: () {},
),
),
],
)
],
),
));
}
}
创建计数器的状态
太棒了!我们现在已经在 lib/store/counter/counter.dart 创建好了我们的计数器。现在,让我们来看看代码,逐行进行解释:
import 'package:mobx/mobx.dart';
// This is our generated file (we'll see this soon!)
part 'counter.g.dart';
// We expose this to be used throughout our project
class Counter = _Counter with _$Counter;
// Our store class
abstract class _Counter with Store {
@observable
int value = 1;
@action
void increment() {
value++;
}
@action
void decrement() {
value--;
}
}
- 我们导入了
mobx.dart,这样就可以访问 Store 以及其他功能了。 - 接下来,我们使用了
part语法组合此类的自动生成的部分。我们暂时还没使用到生成器,但是别担心,我们将会在下一个部分进行这个操作。 - 接下来,我们将暴露
Counter类,该类将与生成的与 MobX 绑定的_$Counter类一起使用。 - 最后,我们使用 Store 类创建一个
_Counter,并定一个@observable属性和@actions以确定 Store 可以与之交互的区域。
MobX 已经帮我们做了绝大部分繁琐的事情,所以我们不需要关心底层是如何实现的。
现在我们已经有了 Counter 类,让我们在终端的该工程目录下通过下面的命令运行 build_runner 和 mobx_codegen:
$ flutter packages pub run build_runner watch
我们现在应该可以看到生成的 counter.g.dart 文件。它看上去类似下面这样:
part of 'counter.dart';
mixin _$Counter on _Counter, Store {
final _$valueAtom = Atom(name: '_Counter.value');
@override
int get value {
_$valueAtom.reportObserved();
return super.value;
}
@override
set value(int value) {
_$valueAtom.context.checkIfStateModificationsAreAllowed(_$valueAtom);
super.value = value;
_$valueAtom.reportChanged();
}
final _$_CounterActionController = ActionController(name: '_Counter');
@override
void increment() {
final _$actionInfo = _$_CounterActionController.startAction();
try {
return super.increment();
} finally {
_$_CounterActionController.endAction(_$actionInfo);
}
}
@override
void decrement() {
final _$actionInfo = _$_CounterActionController.startAction();
try {
return super.decrement();
} finally {
_$_CounterActionController.endAction(_$actionInfo);
}
}
}
这些东西,我们都不需要自己来实现!是不是很棒呀?
与 Store 进行绑定
接下来,我们需要让 counter_page.dart 绑定到 Counter store。让我们再次看看它长什么样,然后进行深入探索:
import 'package:flut_mobx/store/counter/counter.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
class CounterPage extends StatelessWidget {
final Counter counter = Counter();
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text('Flutter and MobX'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Counter',
style: TextStyle(fontSize: 30.0),
),
Observer(
builder: (_) =>
Text('${counter.value}', style: TextStyle(fontSize: 42.0)),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FlatButton.icon(
icon: Icon(Icons.add),
label: Text('Add'),
onPressed: counter.increment,
),
FlatButton.icon(
icon: Icon(Icons.remove),
label: Text('Remove'),
onPressed: counter.decrement,
),
],
)
],
),
));
}
}
让我们深入研究一下:
- 我们导入了
flutter_mobx以及我们的 Counter store,所以之后我们可以用到他们。 - 接下来,我们初始化了
Counter,并将其命名为counter,之后我们就可以轻松监听这个可观察对象的值,或是发出actions:final Counter counter = Counter(); - 我们使用 Observer 监听
counter.value的值。 - 我们将 onPressed 事件绑定到
counter.increment和counter.decrement,它们会将action发送到 Store。
上面这些代码结合起来就完成了我们小型的计数器应用!
总结
希望这篇 MobX 的介绍能够帮到你。我目前仍在持续探索 Flutter 状态管理的最佳实践,所以我也非常期待将来能对该系列进一步的更新。
原文:https://developer.school/flutter-state-management-with-mobx/
注:文章 & 视频本地化和发布已获得作者本人授权
致谢
- 本文作者:Paul Halliday
- 中文字幕翻译: Alex、鑫磊
- 文章翻译:加康、鑫磊
- 头图:Lynn
Flutter 状态管理- 使用 MobX的更多相关文章
- Flutter状态管理之provide和provider的使用区别
说道状态管理不得不说谷歌的亲自开发的两款状态管理Widget:第一个是provide,第二个是provider. 这两个的区别就是一个出来的早,现在好像没整么更新了.第二个是2019才出来的目前的版本 ...
- Flutter状态管理Provider,简单上手
在之前的文章中介绍了 Google 官方仓库下的一个状态管理 Provide.乍一看这俩玩意可能很容易就被认为是同一个东西,仔细一看,这不就差了一个字吗,有什么区别呢. 首先,你要知道的最大的一个区别 ...
- Flutter 状态管理 flutter_Provide
项目的商品类别页面将大量的出现类和类中间的状态变化,这就需要状态管理.现在Flutter的状态管理方案很多,redux.bloc.state.Provide. Scoped Model : 最早的状态 ...
- Flutter | 状态管理特别篇——Provide
前言 今天偶然发现在谷歌爸爸的仓库下出现了一个叫做flutter-provide的状态管理框架,2月8日才第一次提交,非常新鲜.在简单上手之后感觉就是一个字--爽!所以今天就跟大家分享一下这个新的状态 ...
- Flutter 状态管理之BLoC
在正式介绍 BLoC之前, 为什么我们需要状态管理.如果你已经对此十分清楚,那么建议直接跳过这一节.如果我们的应用足够简单,Flutter 作为一个声明式框架,你或许只需要将 数据 映射成 视图 就可 ...
- react状态管理器之mobx
react有几种状态管理器,今天先来整理一下mobx状态管理器,首先了解一下什么是mobx 1.mobx成员: observable action 可以干嘛: MobX 的理念是通过观察者模式对数据做 ...
- Flutter实战视频-移动电商-24.Provide状态管理基础
24.Provide状态管理基础 Flutter | 状态管理特别篇 —— Provide:https://juejin.im/post/5c6d4b52f265da2dc675b407?tdsour ...
- Flutter移动电商实战 --(24)Provide状态管理基础
Flutter | 状态管理特别篇 —— Provide:https://juejin.im/post/5c6d4b52f265da2dc675b407?tdsourcetag=s_pcqq_aiom ...
- 状态管理之 Flux、Redux、Vuex、MobX(概念篇)
本文是对 Flux.Redux.Vuex.MobX 几种常用状态管理模式的总结,偏向于概念层面,不涉及过多代码. 状态管理 什么是状态管理? 状态管理就是,把组件之间需要共享的状态抽取出来,遵循特定的 ...
随机推荐
- Redis基本数据结构之ZSet
1.1Zset(有序集合) Zset保留了集合不能有重复成员的特性,但不同的是,有序集合中的元素可以排序.但是它和列表使用索引下标作为排序依据不同的是,它给每个元素设置一个分数(score)作为排序的 ...
- Spring Boot移除内嵌Tomcat,使用非web方式启动
前言:当我们使用Spring Boot编写了一个批处理应用程序,该程序只是用于后台跑批数据,此时不需要内嵌的tomcat,简化启动方式使用非web方式启动项目,步骤如下: 1.在pom.xml文件中去 ...
- DRF 三大认证的配置及使用方法
目录 三大认证 一.身份认证 1.身份认证配置 1.1 全局配置身份认证模块 1.2 局部配置身份认证模块 2.drf提供的身份认证类(了解) 3.rf-jwt提供的身份认证类(常用) 4.自定义身份 ...
- CSS 书写禅机
这是未来的趋势所向,如是我行. 注意:原文发表于 2017-9-6,随着框架不断演进,部分内容可能已不适用. CSS 日渐惹人憎恶. 究其原因颇多,归根结底,皆因 CSS 给人的感觉总是飘渺迷蒙.变幻 ...
- 使用Docker快速搭建Nginx+PHP-FPM+MySQL+phpMyAdmin环境
一.概述 环境介绍 操作系统:centos 7.6 docker版本:19.03.8 ip地址:192.168.31.34 本文将介绍如何使用单机部署Nginx+PHP-FPM环境 二.Nginx+P ...
- 由endl对printf和cout的思考
[前言]二者的区别就不介绍了.二者使用方法: printf("%s",a); cout<<a<<endl; endl的作用是什么? 一.endl作用 众所周 ...
- Java编程开发之数据图表分析模型
数据统计分析 多曲线图表分析实现 基本需求分析 假设在怪兽出没的年岁,加上年关在即,需要统计分析各个道路卡口车流量出入统计,主要从车流量和车牌地角度出发.如图所示的业务需求: 道路卡口-车流量分析: ...
- Elasticsearch核心技术(一):Elasticsearch环境搭建
磨刀不误砍柴工,要学习Elasticsearch,首先要搭建起来一套学习环境,本文为手把手教你在MacOS上面搭建Elasticsearch学习环境. 1.1 Elasticsearch安装 Elas ...
- ZooKeeper 基本概念并介绍RPC中Netty和Zookeeper的使用
前言 ZooKeeper 是一个分布式协调服务,可用于服务发现,分布式锁,分布式领导选举,配置管理等.Zookeeper提供一个类似Linux文件系统的属性结构,每个节点可存储少量的内存文件,并提供每 ...
- 关于css垂直水平居中的几种方式
css中元素的垂直水平居中是比较常见及较常使用的,在这里向大家介绍一下几种方式. 1.水平居中 margin: 0 auto; 效果图: 而文字的垂直水平居中也比较简单,加上line-height: ...