flutter Bloc 实现原理示例解析
作者:李小轰_Rex 发布时间:2023-07-18 08:00:39
标签:flutter,Bloc,实现原理
序言
在flutter
开发中,我们使用 bloc 框架,基于状态变更进行响应式开发。本篇文章,小轰将 bloc
核心业务块进行拆解简化,聊一聊它的实现思想,bloc 核心能力分为如下两点:
添加事件
event
,将 '事件流' 转换为 '状态流'state
监听
bloc
流,每次state
状态变更,通知widget
更新
下面,用自定义Bloc的方式,来给大家讲解一下Bloc的原理构造
1. 事件流 > 状态流 (中转)
首先,我们将bloc
代码简化,我们来看看bloc
如何将事件流转换为状态流。简化代码如下:
import 'dart:async';
abstract class ACubit<State> {
StreamController<State> _controller = StreamController<State>.broadcast();
State _state;
State get state => _state;
ACubit(this._state);
///发送State状态到流里面
void emit(State state) {
if (_controller.isClosed) return;
if (state == _state) return;
_state = state;
_controller.add(_state);
}
///提供方法外部监听State
StreamSubscription<State> listen(
void Function(State state) onData, {
Function onError,
void Function() onDone,
bool cancelOnError,
}) {
return _controller.stream.listen(
onData,
onError: onError,
onDone: onDone,
cancelOnError: cancelOnError,
);
}
Future<void> close() {
return _controller.close();
}
}
ACubit
提供最基础的能力。提供listen
方法给外部监听 'State' 变更;emit
方法用来响应state
状态变更。
abstract class ABloc<Event, State> extends ACubit<State> {
final _eventController = StreamController<Event>.broadcast();
ABloc(State initState) : super(initState) {
_bindEventToState();
}
///发送事件
void add(Event event) {
if (_eventController.isClosed) return;
_eventController.add(event);
}
///需上层实现 (根据event转成state)
Stream<State> mapEventToState(Event event);
///将事件流(event)转换成状态流(state)
_bindEventToState() {
_eventController.stream
// asyncExpand 将流内容进行类型转换,结果还是流
.asyncExpand((event) => mapEventToState(event))
.listen((nextState) {
///将nextState与当前state进行比对,比对成功后放入流中
emit(nextState);
});
}
}
ABloc
是我们直接使用的基类。在构造函数中调用了_bindEventToState
将事件流转换为状态流。
2. 使用 BlocBuilder 实时监听状态变更, 如何实现的呢?
小轰做了一个简化版的原理讲解:
import 'package:flutter/material.dart';
import 'a_bloc.dart';
class BlocBuilder<T extends ACubit<S>, S> extends StatefulWidget {
final T cubit;
final Widget Function(BuildContext context, S state) builder;
const BlocBuilder({
Key key,
@required this.cubit,
@required this.builder,
}) : super(key: key);
@override
_BlocBuilderState<S> createState() => _BlocBuilderState<S>();
}
class _BlocBuilderState<S> extends State<BlocBuilder> {
void _update() {
setState(() {});
}
@override
void initState() {
///监听state状态变更
widget.cubit?.listen((_) {
_update();
});
super.initState();
}
@override
void dispose() {
widget.cubit?.close();
super.dispose();
}
@override
Widget build(BuildContext context){
return widget.builder(
context,
widget.cubit.state,
);
}
}
封装 BlocBuilder
构造函数中传入自定义的 bloc (继承
ABloc
),builder
传参用于获取每次state
变更通知。在
initState
初始化方法中对cubit
进行状态监听,每次状态变更直接调用setState
方法进行页面更新
调用示例如下:
return BlocBuilder<CountBloc, CountState>(
cubit: CountBloc(CountState(1)),
builder: (context, state) {
return Container(...省略业务代码)
},
)
来源:https://juejin.cn/post/7007683747512320014


猜你喜欢
- Excelapache 为 java开发者们提供了一套excel表格读写的工具:POI ,对于一个小白来说每次读写使用POI需要写一套复杂的
- Java是如何跳出当前多重循环?不建议使用在最外层前面加一个标记A,然后用break A;可以跳出多重循环因为它不会让你的程序变得更加优雅,
- 这篇文章主要介绍了Java调用明华RF读写器DLL文件过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,
- 开门见山,添加水印的方法非常简单,其实就只有3个步骤:1、载入原始图片2、载入水印图片3、保存带有水印的图片实现的原理就是:获取原始图片的宽
- 前言LayoutInflater在开发中使用频率很高,但是一直没有太知道LayoutInflater.from(context).infla
- 目前 Android 已经不推荐使用下列方式创建 Notification实例:Notification notification = ne
- 本文实例讲述了C#简单输出日历的方法。分享给大家供大家参考。具体如下:用C#输出日历,此功能可用于Ajax方式列出计划日程相关的内容,由于是
- 废话不多说了,直接给大家贴代码了,具体代码如下所示:html代码如下:<body><input id="file
- 设置Spring的作用域或者使用枚举值设置单例和多里使用场景自动注入@Primary一个接口有多个实现被spring管理吗,在依赖注入式,s
- 在阿里开发手册的建表规约中有说明,数据库表中应该都要有create_time、update_time字段;那么在开发中,对于这些共有字段的处
- 传统的多分支方式(圈复杂度为6):public String order(String type) { if ("1&
- 生成TAGlogt+Tab键:private static final String TAG = "Extract";生
- bootstrap.yml和bootstrap.properties优先级直接先说结论 bootstrap.properties 优于boo
- 什么是TKMybatisTKMybatis 是基于Mybatis 框架开发的一个工具,内部实现了对单表的基本数据操作,只需要简单继承 TKM
- C#延时函数sleepsleepusing System.Threading; //导入命名空间,类Thread就在此空间中Th
- mybatis初始化SqlSessionFactory失败总结原因有几点1.resources中的xml配置文件放错位置或者是放的太深加载不
- HttpClient使用post方法提交数据 源代码:package post;import Java.io.IOException;imp
- 本文实例讲述了Android实现调用震动的方法。分享给大家供大家参考,具体如下:调用Android系统的震动,只需要一个类 那就是Vibra
- 需要5个类:1.实体类:Person.java2.抽象类:SQLOperate.java(封装了对数据库的操作)3.助手类:DBOpenHe
- 本文实例为大家分享了DatePicker日期滚动选择的使用,供大家参考,具体内容如下效果图为:1.dialog_date.xml:<?