Flutter学习笔记 状态管理学习之bLoc
1.创建一个状态管理
首先使用Stream
来实现的bLoc状态管理如果不手动回收就会一直占用资源,所以在设计之初就需要强调使用完成之后的回收;
abstract class BlocBase {
void dispose();
}
这里的Demo描述的是一个计数参数的管理:
class IncrementBloc implements BlocBase {
int _counter;
StreamController<int> _counterController = StreamController<int>.broadcast();
StreamSink<int> get _inAdd => _counterController.sink;
Stream<int> get outCounter => _counterController.stream;
StreamController _actionControll = StreamController.broadcast();
StreamSink get incrementCounter => _actionControll.sink;
IncrementBloc() {
_counter = 0;
_actionControll.stream.listen(_handleLogic);
}
void _handleLogic(data) {
_counter += 1;
_inAdd.add(_counter);
}
@override
void dispose() {
_actionControll.close();
_counterController.close();
}
}
解释一下设计的属性:
-
StreamController<int>
:Stream管理类,这里主要控制的是计数参数的变化以及监听; -
_inAdd
:计数写入 -
outCounter
:计数输出 -
_actionControll
:动作Stream管理类,这里主要是用于监听它的变化来完成对计数管理的动作; -
incrementCounter
:动作写入;
工作流程很清晰,也就是当对incrementCounter
写入的时候,其监听事件_handleLogic(data)
触发,计数增加1,然后dispose()
方法则将两个Stream管理类进行关闭;
2.如何去使用
使用StreamBuilder<T>
包裹需要动态显示的控件进行使用:
StreamBuilder<int>(
stream: bloc.outCounter,
initialData: bloc._counter,
builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
return Text('now index is ${snapshot.data}');
},
)
当然需要实例化一个状态管理类:
final IncrementBloc bloc = IncrementBloc();
接下来只需要对bloc
进行操作就可以了:
bloc.incrementCounter.add(null);
Demo:
class CounterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final IncrementBloc bloc = IncrementBloc();
return new Scaffold(
appBar: AppBar(
title: Text('bLoc test page'),
),
body: Center(
child: StreamBuilder<int>(
stream: bloc.outCounter,
initialData: bloc._counter,
builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
return Text('now index is ${snapshot.data}');
},
),
),
floatingActionButton: new FloatingActionButton(
backgroundColor: Colors.blue,
child: Icon(
Icons.add,
color: Colors.white,
),
onPressed: () {
bloc.incrementCounter.add(null);
},
),
);
}
}
当点击FAB的时候,就会将计数管理+1,然后居中文字动态显示,避免了StatefulWidget
中动辄全部刷新的情况;
但是当我们用这种方法使用StatelessWidget
来替代StatefulWidget
的时候,并没有类似dispose
的方法来让我们执行Stream关闭的操作:
所以要么就使用StatefulWidget
来实现,但是并不使用其setState
方法来全部刷新;
3.使用StatefulWidget封装
class BlocProvider<T extends BlocBase> extends StatefulWidget {
final T bloc;
final Widget child;
BlocProvider({
Key key,
@required this.child,
@required this.bloc,
}) : super(key: key);
@override
_BlocProviderState createState() => new _BlocProviderState();
static T of<T extends BlocBase>(BuildContext context) {
final type = _typeOf<BlocProvider<T>>();
BlocProvider<T> provider = context.ancestorWidgetOfExactType(type);
return provider.bloc;
}
static Type _typeOf<T>() => T;
}
class _BlocProviderState extends State<BlocProvider<BlocBase>> {
@override
Widget build(BuildContext context) {
return widget.child;
}
@override
void dispose() {
// TODO: implement dispose
widget.bloc.dispose();
super.dispose();
}
}
使用:
IncrementBloc bloc = new IncrementBloc();
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return BlocProvider<IncrementBloc>(
child: CounterPage(),
bloc: bloc);
}),
);
这样的话,BlocProvider在退出销毁dispose
的时候,就会自动调用状态管理中实现的销毁dispose
方法了,当然这明显是一个局部状态管理;
全局状态管理的话,在runApp()
处实现一个就行了。