当咱们使用编译器建立一个新Flutter应用的时候,咱们能够在主界面看到两个小部件StatelessWidget和StatefulWidget。这是两个最多见使用最频繁的小部件了。前端
假如咱们要实现以下图的功能,点击加一。若是使用StatelessWidget,会发现点击的时候count是加一了,可是界面没有刷新。应该使用StatefulWidget,当count加一的时候经过setState(() { _count++;});
方法来改变count的值,这时候就发现界面能够刷新了。git
好比github
import 'package:flutter/material.dart';
class StateManagerDemo extends StatefulWidget {
@override
_StateManagerDemoState createState() => _StateManagerDemoState();
}
class _StateManagerDemoState extends State<StateManagerDemo> {
int _count = 0;
void countCallBack(){
setState(() {
_count++;
});
debugPrint('$_count');
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('StateManagerDemo'),
elevation: 0.0,
),
body: Counter0(_count),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: countCallBack,
),
);
}
}
//------
class Counter0 extends StatelessWidget {
final int count;
Counter0(this.count);
@override
Widget build(BuildContext context) {
return Center(
child: Chip(
label: Text('$count'),
),
);
}
}
//-----
class Counter extends StatelessWidget {
final int count;
final VoidCallback voidCallback;
Counter(this.count,this.voidCallback);
@override
Widget build(BuildContext context) {
return Center(
child: ActionChip(
label: Text('$count'),
onPressed: voidCallback,
),
);
}
}
复制代码
上面的代码中,StateManagerDemo有两个子部件Counter0和Counter。当咱们点击按钮的时候,_count的值++,而后传递给子部件。bash
Counter0是直接接受父部件传过来的参数。网络
Counter不只接收父部件传过来的参数,还有一个回调。这样点击它的时候,会执行父部件中的回调方法,也能改变自身的显示。app
上面的状况是只有一层,Counter小部件中使用了父部件的count这个变量,假如Counter没有用到这个变量而是它的子类用到了这个变量,咱们还要一层一层的传下去吗,这有点麻烦啊,这时候可使用InheritedWidget这个类来管理。less
import 'package:flutter/material.dart';
//使用InheritedWidget来管理状态,
class ContentProvider extends InheritedWidget {
final int count;
final VoidCallback countCallBack;
final Widget child;
const ContentProvider({
this. count,
this. countCallBack,
this. child,
}): assert(child != null),
super(child: child);
static ContentProvider of(BuildContext context) {
return context.inheritFromWidgetOfExactType(
ContentProvider) as ContentProvider;
}
//是否通知继承该小部件的小部件更新
@override
bool updateShouldNotify(ContentProvider old) {
return true;
}
}
class StateManagerDemo extends StatefulWidget {
@override
_StateManagerDemoState createState() => _StateManagerDemoState();
}
class _StateManagerDemoState extends State<StateManagerDemo> {
int _count = 0;
void countCallBack(){
setState(() {
_count++;
});
debugPrint('$_count');
}
@override
Widget build(BuildContext context) {
//ContentProvider放在最外层,指定参数count和callback
return ContentProvider(
count: _count,
countCallBack: countCallBack,
child: Scaffold(
appBar: AppBar(
title: Text('StateManagerDemo'),
elevation: 0.0,
),
body: Counter1(),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: countCallBack,
),
),
);
}
}
class Counter1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
//直接使用ContentProvider中的参数
final int count = ContentProvider.of(context).count;
final VoidCallback voidCallback = ContentProvider.of(context).countCallBack;
return Center(
child: ActionChip(
label: Text('$count'),
onPressed: voidCallback,
),
);
}
}
复制代码
首先定义一个数据提供者ContentProvider继承InheritedWidget,里面定义咱们须要的count和回调。提供一个of方法让外界能够拿到它的实例,方便拿到方法。ide
而后将这个ContentProvider放在主布局的最外层,并传入须要的参数count和callBack。这样它的子部件中就都能访问到这个参数了。布局
最后在子部件Counter1中直接使用ContentProvider中的参数。ui
还可使用ScopedModel来完成状态管理
这是一个第三方的库,该库最初是从Fuchsia代码库中提取的,使用时须要先导入包,在pubspec.yaml文件中添加依赖
dependencies:
scoped_model: 1.0.1
复制代码
pub.dev/packages?q=… 这里能够看到最新版本。使用这个库的时候咱们在StatelessWidget中也能够改变UI
该库主要分为三个部分
好比用ScopedModel实现前面的功能
import 'package:flutter/material.dart';
import 'package:scoped_model/scoped_model.dart';
class CountModel extends Model{
int _count = 0;
int get count =>_count;
void countIncrease(){
_count ++;
//通知改变
notifyListeners();
}
}
class StateModelDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ScopedModel<CountModel>(
model: CountModel() ,
child: Scaffold(
appBar: AppBar(
title: Text('StateModelDemo'),
),
body: Counter2(),
floatingActionButton: ScopedModelDescendant<CountModel>(
rebuildOnChange: false,
builder: (context, child, model) => FloatingActionButton(
child: Icon(Icons.add),
onPressed: (){
model.countIncrease();
},
),
),
),
);
}
}
class Counter2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ScopedModelDescendant<CountModel>(
builder: (context, child, model) => Center(
child: ActionChip(
label: Text('${model.count}'),
onPressed: (){
model.countIncrease();
},
),
),
);
}
}
复制代码
Mobx在前端中用的多,且很好用,因此Flutter也引入了,对于咱们Android开发者来讲跟学前面几个的成本都同样哈哈。
查看版本
github
首先须要去pubspec.yaml文件中引入依赖
dependencies:
mobx: ^0.3.8
flutter_mobx: ^0.3.3
dev_dependencies:
mobx_codegen: ^0.3.9
build_runner: ^1.7.0
复制代码
而后开始使用mobx完成以前的功能
首先建立一个store类
import 'package:mobx/mobx.dart';
//包含生成的文件
part 'state_manager_demo.g.dart';
class Counter = _Counter3 with _$Counter; abstract class _Counter3 with Store {
@observable
int value = 0;
@action
void increment() {
value++;
}
}
复制代码
建立完成以后,咱们会发现part后面的内容和_$Counter都会报错。说是找不到,须要咱们生成。来到AndroidStudio的terminal窗口执行下面命令来生成文件
flutter packages pub run build_runner build
复制代码
这时候就能够看到咱们本身的文件state_manager_demo.dart文件旁边生成了一个新文件state_manager_demo.g.dart,并且不在报错了。
若是想要修改后.g.dart文件也能自动修改执行
pub run build_runner watch
复制代码
下面去界面中使用它
class MobxDemo extends StatefulWidget {
@override
_MobxDemoState createState() => _MobxDemoState();
}
class _MobxDemoState extends State<MobxDemo> {
final Counter counter = Counter();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('StateModelDemo'),
),
body: Center(
child: Observer(
builder: (_)=>ActionChip(
label: Text('${counter.value}'),
onPressed: (){
counter.increment();
},
),
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed:(){
counter.increment();
},
),
);
}
}
复制代码
很简单继承StatefulWidget,须要监听的小部件使用Observer包裹起来。而后建立一个成员变量final Counter counter = Counter();
内部就能够直接使用Counter中的变量和方法了。运行效果跟前面的同样
谷歌亲儿子19年推出的 pub.dev/packages/pr…
添加依赖
provider: 3.1.0+1
复制代码
class Counter with ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners();
}
}
复制代码
void main() => runApp(
MultiProvider(child: MyApp(),providers: [
ChangeNotifierProvider(builder: (_) => Counter()),
],)
);
复制代码
class ProviderDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
final counter = Provider.of<Counter>(context);
return Scaffold(
appBar: AppBar(
title: Text('StateModelDemo'),
),
body: ActionChip(
label: Text('${counter._count}'),
onPressed: (){
Provider.of<Counter>(context, listen: false).increment();
},
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: (){
Provider.of<Counter>(context, listen: false).increment();
},
),
);
}
}
复制代码
OK 完成
综合来看这几种状态管理的方式 ,我感受Provider是最好用的一个,并且是Google亲儿子,后面发展应该也不错。