前言
用简单的计数器来解释BloC架构,便于学习和使用
准备
Stream
InheritedWidget
步骤
步骤1建Counter相关类
抽离出无状态的CounterBody类和CounterActionButton类可单独放在一个dart文件
class CounterBody extends StatelessWidget //抽离后放置一个ActionChip和Text
class CounterActionButton extends StatelessWidget //抽离后放置一个FloatingActionButton
步骤2建放监控的类
建类CounterInherited,可以自动生成
class CounterInherited extends InheritedWidget { //用于放置监控包裹在Scaffold上面
CounterInherited({Key key, this.child, this.bloc}): super(key: key, child: child);
final Widget child; //用于可跟Scaffold ,有变动时后面的不会被重绘,节省资源
final CounterBloc bloc; //绑定数据管理源
static CounterInherited of(BuildContext context) => //后面用于数据的展示和响应事件
context.dependOnInheritedWidgetOfExactType<CounterInherited>();
}
@override
bool updateShouldNotify(CounterInherited oldWidget) {
return true
; }}
步骤3建核心类
建类CounterBloc用于数据的管理,核心作用
class CounterBloc { //核心,作用数据响应
int _count = 0; //存放数据
final _counterActionController = StreamController<int>(); //动作流的控制器
StreamSink<int> get counterActionSink => _counterActionController.sink; //动作流的水槽用于添加数据
final _counterCountController = //动作流监听到数据后让数字流发送数据,StreamBuild会自动更新
StreamController<int>.broadcast(); //数字流有广播功能,收到后都会自动更新
Stream<int> get counterCountStream => _counterCountController.stream; //和StreamBuild的stream参数绑定
CounterBloc() {
_counterActionController.stream.listen(onActionData); } //构造函数里启动监听,有数据后执行onActionData
void onActionData(int data) { //动作流有数据后执行该方法
_count = data + _count; //变量累加
_counterCountController.add(_count); } //然后给数字流发送一个数据,让他的StreamBuild自动更新
void dispose() {
_counterActionController.close(); //释放资源
_counterCountController.close(); }}
步骤4放置监控
用CounterInherited来包裹Scaffold
CounterInherited( //通过CounterInherited.of(context).bloc能回访数据
bloc: CounterBloc(), //数据绑定, 实例化CouterBloc
child: Scaffold(
appBar: AppBar(
title: Text("Bloc的演示"), ),
body: CounterBody(),
floatingActionButton: CounterActionButton(), ), );
步骤5数据展示-按钮
定义类变量_counterBloc,用于临时存放通过CounterInherited.of获取CounterBloc
按钮上数据关联展示用_counterBloc来添加动作流数据
class CounterActionButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
CounterBloc _counterBloc = CounterInherited.of(context).bloc; //获取CounterBloc
return FloatingActionButton(
child: Icon(Icons.add),
onPressed: () { //动作流的监听器已经在构造函数里启动
_counterBloc.counterActionSink.add(1); }, ); }} //listen监听到后onActionData响应
步骤6数据展示-标签和按钮
在类中新建成员_counterBloc通过CounterInherited.of(context).bloc获取CounterBloc
StreamBuilder(
stream: _counterBloc.counterCountStream, //绑定这个,用来监听到数字流后重绘
initialData: 0,
builder: (BuildContext context, AsyncSnapshot snapshot) {
return Container(
child: ActionChip(
avatar: Icon(Icons.add),
label: Text('${snapshot.data}'),
onPressed: () { //和另一个按钮使用同一个,也给数据
_counterBloc.counterActionSink.add(1); }), ); }, ), //让动作流开始监听响应
步骤7数据展示-广播功能
StreamBuilder(
stream: _counterBloc.counterCountStream, //绑定数字流,监听到数据后重绘
initialData: 0,
builder: (BuildContext context, AsyncSnapshot snapshot) {
return Container(
child: Text('利用广播功能接收数据:${snapshot.data}'), ); }, ),
步骤8总体说明
类CounterBloc 数据中心,数据控制
_count 存放数据数字
_counterActionController 动作流控制器,他包含stream,sink,也能add数据
counterActionSink 动作控制的动作监听的水槽 _counterActionController.sink
_counterCountController 数字流控制器
countStream 数字控制的流 _counterController.stream,流上数字和_count对应
构造函数作用开始监听动作流 _counterActionController.stream.listen(onData)
有数据后onActionData(int data)方法,给存放数据的变量累加,以及同时给数字流add(累加后变量)
类CounterInherited 绑定功能
用于包裹Scaffold,赋值通过CounterInherited.of(context).bloc返回CounterBloc
其类成员bloc,用于启动关联实例CounterBloc,一切的开始
棋类成员child ,用来包裹Scaffold,这个后面的Widget数据变化时不会重绘
类StreamBuilder 绑定功能,响应功能
生成Widget并结合CounterInherited.of(context).bloc让数据更好展示
代码
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(MyApp());
SystemUiOverlayStyle systemUiOverlayStyle =
SystemUiOverlayStyle(statusBarColor: Colors.transparent);
SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle);
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: BlocScaffold (),
);
}
}
class BlocScaffold extends StatelessWidget {
@override
Widget build(BuildContext context) {
print("在scaffold上一层");
return CounterInherited(
bloc: CounterBloc(), //数据绑定
child: Scaffold(
appBar: AppBar(
title: Text("Bloc的演示"),
),
body: CounterBody(),
floatingActionButton: CounterActionButton(),
),
);
}
}
class CounterBody extends StatelessWidget {
@override
Widget build(BuildContext context) {
print("body抽离后在scaffold下一层");
CounterBloc _counterBloc = CounterInherited.of(context).bloc; //CounterBloc
return Container(
width: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
StreamBuilder(
stream: _counterBloc.counterCountStream,
initialData: 0,
builder: (BuildContext context, AsyncSnapshot snapshot) {
return Container(
child: Text('利用广播功能接收数据:${snapshot.data}'),
);
},
),
SizedBox(height:10 ),
StreamBuilder(
stream: _counterBloc.counterCountStream,
initialData: 0,
builder: (BuildContext context, AsyncSnapshot snapshot) {
return Container(
child: ActionChip(
avatar: Icon(Icons.add),
label: Text('${snapshot.data}'),
onPressed: () {
_counterBloc.counterActionSink.add(1);
}),
);
},
),
],
),
);
}
}
class CounterActionButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
CounterBloc _counterBloc = CounterInherited.of(context).bloc;
return FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
_counterBloc.counterActionSink.add(1);
},
);
}
}
class CounterInherited extends InheritedWidget {
CounterInherited({Key key, this.child, this.bloc})
: super(key: key, child: child);
final Widget child;
final CounterBloc bloc;
static CounterInherited of(BuildContext context) => //后面用于数据的展示和响应事件
context.dependOnInheritedWidgetOfExactType<CounterInherited>();
@override
bool updateShouldNotify(CounterInherited oldWidget) {
return true;
}
}
class CounterBloc {
int _count = 0;
final _counterActionController = StreamController<int>.broadcast();
StreamSink<int> get counterActionSink => _counterActionController.sink;
final _counterCountController = StreamController<int>.broadcast();
Stream<int> get counterCountStream => _counterCountController.stream;
CounterBloc() {
_counterActionController.stream.listen(onActionData);
}
void onActionData(int data) {
_count = data + _count;
_counterCountController.add(_count);
}
void dispose() {
_counterActionController.close();
_counterCountController.close();
}
}