Flutter_Bloc 异步通信基本使用
1.简介
Bloc全称是 Business Logic Component(业务逻辑组件),主要作用就是将UI视图与数据逻辑处理分割开来。Bloc用法以及功能上与谷歌官方提供的Provider基本一致,二者差异较小,与Android中ViewModel作用类似, 在构建MVVM时,该层主要是分离业务逻辑,VM层。在BLoC模式下的应用程序,一般会有全局的BLoC,每一个页面也会对应有一个独立的BLoC
2基本使用
1.了解原理
-
Bloc为中间逻辑层,与Android中ViewModel一致
-
BlockBuilder:消费或者说监听,与provider中Consumer一致,类似于LiveData的监听
-
BlocObserver:进行事件观察的接口
-
BlocProvider:可通过BlocProvider.of (context)向其子级提bloc。它被作为依赖项注入(DI)部件(widget),以便可以将一个bloc的单个实例提供给子树中的多个部件(widgets)。
-
BlocListener:监听状态
-
RepositoryProvider:
之前开发过APP的同学可能用过Repository模式,就是将APP中的数据需求抽取成Repository接口,可以根据不同的数据源来定义不同的实现,比如LocalRepository和NetRepository,通过代理来得到最终的Repository实现。通常会把Repository作为单例来让全局共享数据。数据缓存本来就是很占内存的,如果使用单例会导致内存利用效率不高。
Bloc也对数据的共享也做了支持,可以更好的控制数据仓库的生命周期。RepositoryProvider就是这样的控件,可以将存储库的单个实例提供给子树中的多个部件(widgets)。RepositoryProvider不需要指定泛型类型,只用指定create方法和child结点即可。
说明:BlocProvider,如果在APP页面的home节点开始创建,所有子控件都能拿到
依赖:
flutter_bloc: 7.0.0
2.发送事件
BlocProvider.of<TimeCounterBloc>(context).add(0);
3.发送数据
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:intl/intl.dart';
class TimeCounterBloc extends Bloc<int, String> {
TimeCounterBloc(String initialState) : super(initialState);
///业务逻辑处理 [event] 事件标识
@override
Stream<String> mapEventToState(int event) async* {
DateTime dateTime= DateTime.now();
String formatTime = DateFormat("HH:mm:ss").format(dateTime);
///发射更新数据
yield formatTime;
}
}
——————通过add方法,以及event事件,来识别相应的请求,与Provider不同
4.接收数据,
BlocBuilder<TimeCounterBloc, String>(
builder: (context, time) {
///在这里 time 就是BloC回传的数据处理结果
///当然在这里是一个 String 类型
return Container(
///外边距
margin: EdgeInsets.only(left: 12,top: 12),
child: Text(
'$time',
style: TextStyle(fontSize: 22.0, color: Colors.red),
),
);
},
);
5.关闭
先关闭网络耗时请求,在关闭流
@override
void dispose() {
super.dispose();
///取消计时器
_timer.cancel();
BlocProvider.of<TimeCounterBloc>(context).close();
}
代码如下:
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_first/day52Bloc/test01/TimeCounterBloc.dart';
///flutter应用程序中的入口函数
void main() => runApp(BlocMainApp());
///应用的根布局
class BlocMainApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
///构建Materia Desin 风格的应用程序
return BlocProvider<TimeCounterBloc>(
create: (context) => TimeCounterBloc(""),
child: MaterialApp(
///Android应用程序中任务栏中显示应用的名称
title: "配制",
theme: ThemeData(
accentColor: Colors.blue,
///默认是 Brightness.light
brightness: Brightness.light,
),
///默认的首页面
home: TimePage(),
),
);
}
}
class TimePage extends StatefulWidget {
TimePage({Key key}) : super(key: key);
@override
_TimePageState createState() {
return _TimePageState();
}
}
class _TimePageState extends State<TimePage> {
@override
void initState() {
super.initState();
}
@override
void dispose() {
BlocProvider.of<TimeCounterBloc>(context).close();
super.dispose();
}
Widget buildBlocBuilder() {
return BlocBuilder<TimeCounterBloc, String>(
builder: (context, time) {
return Container(
margin: EdgeInsets.only(left: 12, top: 12),
child: Text(
'$time',
style: TextStyle(fontSize: 22.0, color: Colors.red),
),
);
},
);
}
@override
Widget build(BuildContext context) {
return Column(
children: [
SizedBox(height: 50),
Container(
width: 200,
height: 200,
color: Colors.red,
child: OutlinedButton(
child: Text("bloc"),
onPressed: () {
BlocProvider.of<TimeCounterBloc>(context).add(0);
},
),
),
Container(
margin: EdgeInsets.only(top: 10, bottom: 10),
child: Text("点击"),
),
buildBlocBuilder()
],
);
}
}
TimeCount:
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:intl/intl.dart';
///Bolc 的泛型数据类型
///在这里 int 代表输入的事件类型
/// String 代表输出的数据结果
class TimeCount extends Bloc<int, String> {
///默认构造
///[initialState]默认的数据
TimeCount(String initialState) : super(initialState);
///业务逻辑处理 [event] 事件标识
@override
Stream<String> mapEventToState(int event) async* {
///获取当前的时间
DateTime dateTime= DateTime.now();
///格式化时间 import 'package:intl/intl.dart';
///需要添加 intl 依赖
String formatTime = DateFormat("HH:mm:ss").format(dateTime);
///发射更新数据
yield formatTime;
}
}
6MultiBlocProvider
多个BlocProvider合并为一个BlocProvider的组件,用法等价于Provider中MultiProvider
class BlocProviders extends StatelessWidget {
BlocProviders({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
// TODO: implement build
return MultiBlocProvider(
providers: [
BlocProvider<TimeCount03>(
create: (BuildContext context) => TimeCount03("00:00:00"),
),
BlocProvider<RandomCount03>(
create: (BuildContext context) => RandomCount03("00:00:00"),
),
],
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_first/day52Bloc/Demo03/RandomCount03.dart';
import 'package:flutter_first/day52Bloc/test01/TimeCount03.dart';
import 'TimeCount03.dart';
///flutter应用程序中的入口函数
void main() => runApp(BlocMainApp());
///应用的根布局
class BlocMainApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
///构建Materia Desin 风格的应用程序
return BlocProvider<TimeCount03>(
create: (context) => TimeCount03(""),
child: MaterialApp(
///Android应用程序中任务栏中显示应用的名称
title: "配制",
theme: ThemeData(
accentColor: Colors.blue,
///默认是 Brightness.light
brightness: Brightness.light,
),
///默认的首页面
home: TimePage(),
),
);
}
}
class BlocProviders extends StatelessWidget {
BlocProviders({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
// TODO: implement build
return MultiBlocProvider(
providers: [
BlocProvider<TimeCount03>(
create: (BuildContext context) => TimeCount03("00:00:00"),
),
BlocProvider<RandomCount03>(
create: (BuildContext context) => RandomCount03("00:00:00"),
),
],
);
}
}
class TimePage extends StatefulWidget {
TimePage({Key key}) : super(key: key);
@override
_TimePageState createState() {
return _TimePageState();
}
}
class _TimePageState extends State<TimePage> {
@override
void initState() {
super.initState();
}
@override
void dispose() {
BlocProvider.of<TimeCount03>(context).close();
BlocProvider.of<RandomCount03>(context).close();
super.dispose();
}
Widget buildBlocBuilder() {
return BlocBuilder<TimeCount03, String>(
builder: (context, time) {
return Container(
margin: EdgeInsets.only(left: 12, top: 12),
child: Text(
'$time',
style: TextStyle(fontSize: 22.0, color: Colors.red),
),
);
},
);
}
Widget buildBlocBuilder2() {
return BlocBuilder<RandomCount03, String>(builder: (context, time) {
return Container(
margin: EdgeInsets.only(left: 12, top: 12),
child: Text(
'$time',
style: TextStyle(fontSize: 22.0, color: Colors.red),
),
);
});
}
@override
Widget build(BuildContext context) {
return Column(
children: [
SizedBox(height: 50),
Container(
width: 200,
height: 200,
color: Colors.red,
child: OutlinedButton(
child: Text("bloc"),
onPressed: () {
BlocProvider.of<TimeCount03>(context).add(0);
},
),
),
Container(
width: 200,
height: 200,
color: Colors.yellow,
child: OutlinedButton(
child: Text("点击"),
onPressed: () {
BlocProvider.of<RandomCount03>(context).add(0);
},
),
),
buildBlocBuilder(),
buildBlocBuilder2()
],
);
}
}
7.buildWhen
用于向BlocBuilder提供可选的条件,返回 true,那么将调用state执行视图的重新构建,如果返回false,则不会执行视图的重建操作。
回调拦截使用
buildWhen: (String previous, String current) {
return true;
},
8.buildConsumer
不在解答,与provider中Consumer一致,BlocBuilder相当于provider中selector
9.RepositoryProvider
RepositoryProvider 通过RepositoryProvider.of(context)为其子项提供存储库。它使用依赖注入将存储库的单个实例提供给子树中的多个小部件。BlocProvider应该用于提供Bloc,而RepositoryProvider只能用于存储库。
RepositoryProvider(
create: (context) => RepositoryA(),
child: ChildA(),
);
获取,所以该种方式,可以用于页面跳转之间大量信息的传递,少数信息可以直接参数传递,数据量较大,可以通过该种方式传递
// with extensions
context.read<RepositoryA>();
// without extensions
RepositoryProvider.of<RepositoryA>(context)