文 / Paul Halliday, developer.school 创始人

众所周知,状态管理是每个软件项目都需要持续迭代更新的方向。它并不是一个「一次性」的工作,

而需要不断确保你遵循的最佳实践能够让你的工程保持良好的可维护性。

要在 Flutter 中高效地使用 MobX ,需要遵循以下原则:

  1. 我们能访问任意状态中的可观察对象(即在我们应用运行过程中发生变化的变量)。
  2. 我们可以在 View 中展示这些状态,并响应 Action 意图。
  3. 我们可以修改状态,从而更新可观察对象以及相应的 View。

那么它的优势在哪呢?答案是,通过 MobX 完成这一切将会变得超级简单!codegen 工具可以帮我们完成绝大部分模版化的工作。

初始化项目

让我们从创建一个全新的 Flutter 工程开始吧:

# New Flutter project
$ flutter create f_mobx && cd f_mobx # Open in VS Code
$ code .

下一步,我们得在 pubspec.yaml 中拉取一些依赖 (dependenciesdev_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--;
}
}
  1. 我们导入了 mobx.dart,这样就可以访问 Store 以及其他功能了。
  2. 接下来,我们使用了 part 语法组合此类的自动生成的部分。我们暂时还没使用到生成器,但是别担心,我们将会在下一个部分进行这个操作。
  3. 接下来,我们将暴露 Counter 类,该类将与生成的与 MobX 绑定的 _$Counter 类一起使用。
  4. 最后,我们使用 Store 类创建一个 _Counter,并定一个 @observable 属性和 @actions 以确定 Store 可以与之交互的区域。

MobX 已经帮我们做了绝大部分繁琐的事情,所以我们不需要关心底层是如何实现的。

现在我们已经有了 Counter 类,让我们在终端的该工程目录下通过下面的命令运行 build_runnermobx_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,
),
],
)
],
),
));
}
}

让我们深入研究一下:

  1. 我们导入了 flutter_mobx 以及我们的 Counter store,所以之后我们可以用到他们。
  2. 接下来,我们初始化了 Counter,并将其命名为 counter,之后我们就可以轻松监听这个可观察对象的值,或是发出 actions:final Counter counter = Counter();
  3. 我们使用 Observer 监听 counter.value 的值。
  4. 我们将 onPressed 事件绑定到 counter.incrementcounter.decrement,它们会将 action 发送到 Store。

上面这些代码结合起来就完成了我们小型的计数器应用!

总结

希望这篇 MobX 的介绍能够帮到你。我目前仍在持续探索 Flutter 状态管理的最佳实践,所以我也非常期待将来能对该系列进一步的更新。

原文:https://developer.school/flutter-state-management-with-mobx/

注:文章 & 视频本地化和发布已获得作者本人授权

致谢

  • 本文作者:Paul Halliday
  • 中文字幕翻译: Alex、鑫磊
  • 文章翻译:加康、鑫磊
  • 头图:Lynn

Flutter 状态管理- 使用 MobX的更多相关文章

  1. Flutter状态管理之provide和provider的使用区别

    说道状态管理不得不说谷歌的亲自开发的两款状态管理Widget:第一个是provide,第二个是provider. 这两个的区别就是一个出来的早,现在好像没整么更新了.第二个是2019才出来的目前的版本 ...

  2. Flutter状态管理Provider,简单上手

    在之前的文章中介绍了 Google 官方仓库下的一个状态管理 Provide.乍一看这俩玩意可能很容易就被认为是同一个东西,仔细一看,这不就差了一个字吗,有什么区别呢. 首先,你要知道的最大的一个区别 ...

  3. Flutter 状态管理 flutter_Provide

    项目的商品类别页面将大量的出现类和类中间的状态变化,这就需要状态管理.现在Flutter的状态管理方案很多,redux.bloc.state.Provide. Scoped Model : 最早的状态 ...

  4. Flutter | 状态管理特别篇——Provide

    前言 今天偶然发现在谷歌爸爸的仓库下出现了一个叫做flutter-provide的状态管理框架,2月8日才第一次提交,非常新鲜.在简单上手之后感觉就是一个字--爽!所以今天就跟大家分享一下这个新的状态 ...

  5. Flutter 状态管理之BLoC

    在正式介绍 BLoC之前, 为什么我们需要状态管理.如果你已经对此十分清楚,那么建议直接跳过这一节.如果我们的应用足够简单,Flutter 作为一个声明式框架,你或许只需要将 数据 映射成 视图 就可 ...

  6. react状态管理器之mobx

    react有几种状态管理器,今天先来整理一下mobx状态管理器,首先了解一下什么是mobx 1.mobx成员: observable action 可以干嘛: MobX 的理念是通过观察者模式对数据做 ...

  7. Flutter实战视频-移动电商-24.Provide状态管理基础

    24.Provide状态管理基础 Flutter | 状态管理特别篇 —— Provide:https://juejin.im/post/5c6d4b52f265da2dc675b407?tdsour ...

  8. Flutter移动电商实战 --(24)Provide状态管理基础

    Flutter | 状态管理特别篇 —— Provide:https://juejin.im/post/5c6d4b52f265da2dc675b407?tdsourcetag=s_pcqq_aiom ...

  9. 状态管理之 Flux、Redux、Vuex、MobX(概念篇)

    本文是对 Flux.Redux.Vuex.MobX 几种常用状态管理模式的总结,偏向于概念层面,不涉及过多代码. 状态管理 什么是状态管理? 状态管理就是,把组件之间需要共享的状态抽取出来,遵循特定的 ...

随机推荐

  1. 使用 Tye 辅助开发 k8s 应用竟如此简单(五)

    续上篇,这篇我们来进一步探索 Tye 更多的使用方法.本篇我们来了解一下如何在 Tye 中实现对分布式链路追踪. Newbe.Claptrap 是一个用于轻松应对并发问题的分布式开发框架.如果您是首次 ...

  2. JAVA 判断一个字符串是否是合法的日期格式?

    采用SimpleDateFormat类的parse方法进行判断,如果转换不成功,就会出现异常.另外,还需要判断字符串的长度,若不判断,第二个字符串就会验证通过,实际上也不是合法的.话不多说,且看代码: ...

  3. Linux安装jdk(两种方式)

    最近在研究大数据方面的东西,业务场景是从设备采集数据经过处理然后存放DB. 建设上面的环境第一步肯定是安装jdk,所以和大家一起学一下基本知识centos7.5安装jdk1.8. 安装jdk有两种方法 ...

  4. Java并发之ThreadPoolExecutor源码解析(三)

    Worker 先前,笔者讲解到ThreadPoolExecutor.addWorker(Runnable firstTask, boolean core),在这个方法中工作线程可能创建成功,也可能创建 ...

  5. 使用dlopen加载动态库

    目录 概述 接口 C CMakeLists.txt src/main.c src/add.c ./dlopen_test C++ CMakeLists.txt src/main.cpp src/add ...

  6. Linux:使用systemd管理进程

    Blog:博客园 个人 概述 systemd是目前Linux系统上主要的系统守护进程管理工具,由于init一方面对于进程的管理是串行化的,容易出现阻塞情况,另一方面init也仅仅是执行启动脚本,并不能 ...

  7. STM32 ADC详细篇(基于HAL库)

    一.基础认识 ADC就是模数转换,即将模拟量转换为数字量 l  分辨率,读出的数据的长度,如8位就是最大值为255的意思,即范围[0,255],12位就是最大值为4096,即范围[0,4096] l  ...

  8. python基础学习之字符串的功能方法

    字符串:str的功能记录(该类需要记忆) .isdecimal():意思是判断是否由数字构成,仅仅可以解析"123" a='123'    d=a.isdecimal()    p ...

  9. 使用jQuery实现ajax请求

    <%-- Created by IntelliJ IDEA. User: Administrator Date: 2021/3/13 Time: 14:54 To change this tem ...

  10. P1162_填涂颜色(JAVA语言)(速看!全洛谷最暴力解法!QAQ)

    思路:看了看数据n<=30,于是我们可以暴力求解(主要是BFS学的不咋地~2333).枚举每个0的位置,看上下左右四个方向上是否都有1.都有1的话说明被1包围,即在闭合圈的内部,开个数组标记一下 ...