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
0
投稿
猜你喜欢
- 目标效果: 点击动画按钮之后每张牌各自旋转 散开到屏幕上半部分的任意位置之后回到初始位置 比较像LOL男刀的技能动画 : )1: 创建卡牌对
- 最近没事写了一个简易浏览器,在刚开始写的时候遇到一些问题,主要的问题就是如何在自己的webview中显示所有的网页数据,不过不指
- 在实际应用中,我们往往有需要比较两个自定义对象大小的地方。而这些自定义对象的比较,就不像简单的整型数据那么简单,它们往往包含有许多的属性,我
- 井字棋游戏要求在3乘3棋盘上,每行都相同或者每列都相同再或者对角线相同,则胜出.因此我们可以使用一个二维数组来表示棋盘,判断胜负只需要判断数
- “Java is still not dead—and people are starting to figure that out.”本教
- 本文实例讲述了Java实现接口的枚举类。分享给大家供大家参考,具体如下:一 点睛枚举类也可以实现一个或多个接口。与普通类实现一个或多个接口完
- 虽然说模块通信、路由协议在Android已经不新鲜了,但是如果脱离了那些优秀的开源库我们从零开始自己造一个库,有时候重复造轮子会让自己对所谓
- 需求: 给定一个URL地址, 例如: http://www.cncounter.com/tools/shorturl.php, 解析对应的I
- 开发环境win10Android Studio效果用于多级菜单展示,或选择。如 每个省,市,县;如 树木的病虫害;关键代码 @overrid
- [LeetCode] 159. Longest Substring with At Most Two Distinct Characters
- 具体可见http://developer.android.com/tools/debugging/ddms.html。 DDMS为IDE和e
- 有人问我,怎么判断一个点是不是在多边形内,本来想着把这个多边形分成一个又一个三角形,如图, 然后判断这个点是不是在某个三角形中,如
- 内容简介本篇将介绍 Flutter 中如何完成图片上传,以及上传成功后的表单提交。涉及的知识点如下:图片选择插件wechat_assets_
- 序言小编在项目中有遇到使用 flutter 实现扫码枪接入的需求。为方便使用,小编把能力封装成 package 并发布。好记性不如烂笔头,下
- 1.引言在开发中,拖放是一种比较常见的手势操作,使用它能够让应用的交互更加地便捷和友好,本文将简要介绍如何为Android中的View添加拖
- UI 妹纸又给了个图叫我做,我一看是这样的:我们首先把这个控件划分成 几个部分:1.底下部分的直线 :2.左右两边的半圆
- 在我们实现某些功能时,可能会有倒计时的需求。比如发送短信验证码,发送成功后可能要求用户一段时间内不能再次发送,这时候我们就需要进行倒计时,时
- 本篇给大家详细讲解了MTKAndroid平台开发流程,大致分为44个步骤,我们把每个步骤的命令详细讲解了下,一起来学习下。1.拷贝代码仓库从
- 一、Monkey 是什么?Monkey 就是SDK中附带的一个工具。二、Monkey 测试的目的?:该工具用于进行压力测试。 然后开发人员结
- 前言前面介绍了APP顶部导航栏AppBar,今天来介绍下Flutter实现APP底部导航栏。我们以仿写微信的底部导航栏来举例说明。要实现类似