By Paul Halliday, founder, Developer. school
It is well known that state management is an area where every software project needs continuous iteration. It’s not a “one off” job, but a constant effort to ensure that the best practices you follow keep your project maintainable.
To use MobX efficiently in Flutter, follow the following principles:
- We can access observables in any state (that is, variables that change as our application runs).
- We can display these states in the View and respond to Action intents.
- We can modify the state to update the observable and the corresponding View.
So what’s the advantage? The answer is, it’s super easy to do it all through MobX! The CodeGen tool does most of the template work for us.
Initialize the project
Let’s start by creating a brand new Flutter project:
# New Flutter project
$ flutter create f_mobx && cd f_mobx
# Open in VS Code
$ code .
Copy the code
Next, we need to pull dependencies (dependencies and dev_dependencies) from pubspec.yaml:
dependencies:
flutter:
sdk: flutter
mobx:
flutter_mobx:
dev_dependencies:
flutter_test:
sdk: flutter
build_runner: ^ 1.3.1
mobx_codegen:
Copy the code
Dart can then create a brand new MaterialApp to place our 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 newMaterialApp( home: CounterPage(), ); }}Copy the code
Next, we need to create the CounterPage in lib/pages/ Counter_page.dart and finish building the user interface. It includes an increase button and a decrease button.
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: () {}, ), ), ], ) ], ), )); }}Copy the code
Create the state of the counter
That’s great! We are now in the lib/store/counter/counter. The dart created our counter. Now, let’s look at the code, line by line:
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
voiddecrement() { value--; }}Copy the code
- We import
mobx.dart
“, so you can access the Store and other functions. - Next, we use
part
The automatically generated part of a syntax combination class. We haven’t used the generator yet, but don’t worry, we’ll do it in the next section. - Next, we will be exposed
Counter
Class, which will be associated with the generated mobx-bound_$Counter
Class used together. - Finally, we create one using the Store class
_Counter
And decide on one@observable
Properties and@actions
To identify areas with which the Store can interact.
MobX already does most of the heavy lifting for us, so we don’t need to worry about how the underlying implementation works.
Now that we have the Counter class, let’s run build_Runner and mobx_codegen in that project directory on the terminal with the following command:
$ flutter packages pub run build_runner watch
Copy the code
We should now see the generated counter. G.art file. It looks something like this:
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); }}}Copy the code
None of these things we need to achieve ourselves! Isn’t it great?
Bind to Store
Next, we need to bind counter_page.dart to the Counter Store. Let’s see what it looks like again and explore further:
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, ), ], ) ], ), )); }}Copy the code
Let’s dig deeper:
- We import
flutter_mobx
And our Counter Store, so we can use them later. - Next, we initialize
Counter
And name itcounter
, then we can easily listen to the value of the observable, or emitActions: Final Counter Counter = Counter()
; - We use the Observer to listen
counter.value
The value of the. - We bind the onPressed event to
counter.increment
和counter.decrement
They willaction
Send to Store.
The above code combined to complete our small counter application!
conclusion
Hope this introduction to MobX has helped you. I am currently continuing to explore best practices for Flutter state management, so I look forward to further updates to this series in the future.
: the original developer. School/flutter – sta… Note: localization and distribution of the article & video have been authorized by the author himself
Thank you
- By Paul Halliday
- Chinese Subtitles: Alex, Xin Lei
- Jia Kang, Xin Lei
- The first figure: Lynn