题记
—— 执剑天涯,从你的点滴积累开始,所及之处,必精益求精。
Flutter是谷歌推出的最新的移动开发框架。
在 Flutter 中可用于异步通信的方案有如下:
BloC 全称是 Business Logic Component(业务逻辑组件),主要作用就是将业务逻辑和UI组件分离开。
在Flutter项目开发中,一般的项目中,会有网络请求的代码与Widget构建的UI界面写一起,随着业务的不断积累,代码量也越来越大,维护的复杂度也会随着增加。
BLoC模式可以将Widget构建UI的代码与业务处理的代码分离出来,在BLoC模式下的应用程序,一般会有全局的BLoC,每一个页面也会对应有一个独立的BLoC。
使用BloC模式,Flutter项目应用里的所有组件都在一个事件流,其中一部分组件可以订阅事件,另一部分组件则消费事件
BloC是一种架构模式也是一种编程思想,在Flutter中使用BloC时,首先要引入bloc库
dependencies: flutter_bloc: ^6.0.6
然后将依赖库拉取到本地
flutter packages get
在Flutter BloC模式开发中常用组件有BlocBuilder、BlocProvider、BlocListener和BlocConsumer等等。
在这里使用Bloc模式开发一个时间计时器 运行效果如下图所示:
首先来看程序入口,在这里使用到了 BlocProvider ,BlocProvider相当于一个组合者,它将 Bloc 、事件、消费组合在一起,在本文章 第四小节有详细概述,代码如下:
///flutter应用程序中的入口函数 void main() => runApp(BlocMainApp()); ///应用的根布局 class BlocMainApp extends StatelessWidget { @override Widget build(BuildContext context) { ///构建Materia Desin 风格的应用程序 return BlocProvider<CounterBloc>( create: (context) => CounterBloc(""), child: MaterialApp( ///Android应用程序中任务栏中显示应用的名称 title: "配制", theme: ThemeData( accentColor: Colors.blue, ///默认是 Brightness.light brightness: Brightness.light, ), ///默认的首页面 home: TestBlocTimePage(), ), ); } }
对于 TestBlocTimePage 就是 MaterialApp中设置默认显示的 home 首页面,是自定义的一个 Widget 页面,在这里使用 Scaffold 来构建页面主体,然后初始化了一个 计时器Timer,代码如下:
import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'dart:async'; import 'bloc_time.dart'; ///Bloc 初探 class TestBlocTimePage extends StatefulWidget { @override State<StatefulWidget> createState() { return _TestABPageState(); } } class _TestABPageState extends State { ///计时器 Timer _timer; @override void initState() { super.initState(); ///间隔1秒执行时间 _timer= Timer.periodic(Duration(milliseconds: 1000), (timer) { ///发送事件 BlocProvider.of<TimeCounterBloc>(context).add(0); }); } @override void dispose() { super.dispose(); ///取消计时器 _timer.cancel(); } @override Widget build(BuildContext context) { ///页面主体脚手架 return Scaffold( appBar: AppBar( title: Text("Bloc "), ), body:buildBlocBuilder(), ); } ///代码清单1-1 /// 通过 BlocBuilder 来消费事件结果 Widget buildBlocBuilder() { return 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), ), ); }, ); } }
在这里定义的 BlocBuilder,本文第三小节有分析。
定义的 Bloc 角色,代码如下:
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:intl/intl.dart'; ///Bolc 的泛型数据类型 ///在这里 int 代表输入的事件类型 /// String 代表输出的数据结果 class TimeCounterBloc extends Bloc<int, String> { ///默认构造 ///[initialState]默认的数据 TimeCounterBloc(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; } }
BlocBuilder与StreamBuilder的作用一样,用来消费事件结果,就是显示数据结果,它的构建构建如下:
class BlocBuilder<C extends Cubit<S>, S> extends BlocBuilderBase<C, S> { /// {@macro bloc_builder} const BlocBuilder({ Key key, @required this.builder, C cubit, BlocBuilderCondition<S> buildWhen, }) : assert(builder != null), super(key: key, cubit: cubit, buildWhen: buildWhen); ... ... }
builder 参数为必选参数,用来构建消费的 UI 视图,它需要一个 BlocWidgetBuilder,BlocWidgetBuilder定义如下:
typedef BlocWidgetBuilder<S> = Widget Function(BuildContext context, S state);
BlocWidgetBuilder 的入参数二 state 就是 BloC 中发射的数据。
buildWhen参数,用于向BlocBuilder提供可选的条件,返回 true,那么将调用state执行视图的重新构建,如果返回false,则不会执行视图的重建操作。
Widget buildBlocBuilder() { return BlocBuilder<TimeCounterBloc, String>( ///条件判断是否更新视图 /// 参数 previous 上一次的数据 /// 参数 current 当前的数据 buildWhen: (String previous,String current){ print("previous $previous current $current"); return true; }, ///入参 time 为BloC发射的数据 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), ), ); }, ); }
BlocProvider相当于一个组合者,它将 Bloc 、事件、消费组合在一起,它是一个组件。
可以通过BlocProvider.of (context)向其子级提供bloc,如上述的 add 方法发送事件
BlocProvider.of<TimeCounterBloc>(context).add(0);
MultiBlocProvider是一个用于将多个BlocProvider合并为一个BlocProvider的组件。
MultiBlocProvider( providers: [ BlocProvider<BlocA>( create: (BuildContext context) => BlocA(), ), BlocProvider<BlocB>( create: (BuildContext context) => BlocB(), ), BlocProvider<BlocC>( create: (BuildContext context) => BlocC(), ), ], child: 子页面视图, )
然后在子页面中 通过 BlocBuilder 分别引用不同的 Bloc 就可以,小编这也有 Demo 点击查看详情
完毕
以小编的性格,要实现百万Demo随时复制粘贴肯定是需要源码的
当然以小编的性格,肯定是要有视频录制的,目前正在录制中,你可以关注一下 西瓜视频 --- 早起的年轻人 随后会上传
原创声明,本文系作者授权云+社区发表,未经许可,不得转载。
如有侵权,请联系 yunjia_community@tencent.com 删除。
我来说两句