flutter?Bloc?實(shí)現(xiàn)原理示例解析
序言
在flutter開(kāi)發(fā)中,我們使用 bloc 框架,基于狀態(tài)變更進(jìn)行響應(yīng)式開(kāi)發(fā)。本篇文章,小轟將 bloc 核心業(yè)務(wù)塊進(jìn)行拆解簡(jiǎn)化,聊一聊它的實(shí)現(xiàn)思想,bloc 核心能力分為如下兩點(diǎn):
- 添加事件
event,將 '事件流' 轉(zhuǎn)換為 '狀態(tài)流'state - 監(jiān)聽(tīng)
bloc流,每次state狀態(tài)變更,通知widget更新
下面,用自定義Bloc的方式,來(lái)給大家講解一下Bloc的原理構(gòu)造
1. 事件流 > 狀態(tài)流 (中轉(zhuǎn))
首先,我們將bloc代碼簡(jiǎn)化,我們來(lái)看看bloc如何將事件流轉(zhuǎn)換為狀態(tài)流。簡(jiǎn)化代碼如下:
import 'dart:async';
abstract class ACubit<State> {
StreamController<State> _controller = StreamController<State>.broadcast();
State _state;
State get state => _state;
ACubit(this._state);
///發(fā)送State狀態(tài)到流里面
void emit(State state) {
if (_controller.isClosed) return;
if (state == _state) return;
_state = state;
_controller.add(_state);
}
///提供方法外部監(jiān)聽(tīng)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提供最基礎(chǔ)的能力。提供listen方法給外部監(jiān)聽(tīng) 'State' 變更;emit方法用來(lái)響應(yīng)state狀態(tài)變更。
abstract class ABloc<Event, State> extends ACubit<State> {
final _eventController = StreamController<Event>.broadcast();
ABloc(State initState) : super(initState) {
_bindEventToState();
}
///發(fā)送事件
void add(Event event) {
if (_eventController.isClosed) return;
_eventController.add(event);
}
///需上層實(shí)現(xiàn) (根據(jù)event轉(zhuǎn)成state)
Stream<State> mapEventToState(Event event);
///將事件流(event)轉(zhuǎn)換成狀態(tài)流(state)
_bindEventToState() {
_eventController.stream
// asyncExpand 將流內(nèi)容進(jìn)行類(lèi)型轉(zhuǎn)換,結(jié)果還是流
.asyncExpand((event) => mapEventToState(event))
.listen((nextState) {
///將nextState與當(dāng)前state進(jìn)行比對(duì),比對(duì)成功后放入流中
emit(nextState);
});
}
}
ABloc 是我們直接使用的基類(lèi)。在構(gòu)造函數(shù)中調(diào)用了_bindEventToState將事件流轉(zhuǎn)換為狀態(tài)流。
2. 使用 BlocBuilder 實(shí)時(shí)監(jiān)聽(tīng)狀態(tài)變更, 如何實(shí)現(xiàn)的呢?
小轟做了一個(gè)簡(jiǎn)化版的原理講解:
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() {
///監(jiān)聽(tīng)state狀態(tài)變更
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
- 構(gòu)造函數(shù)中傳入自定義的 bloc (繼承
ABloc),builder傳參用于獲取每次state變更通知。 - 在
initState初始化方法中對(duì)cubit進(jìn)行狀態(tài)監(jiān)聽(tīng),每次狀態(tài)變更直接調(diào)用setState方法進(jìn)行頁(yè)面更新
調(diào)用示例如下:
return BlocBuilder<CountBloc, CountState>(
cubit: CountBloc(CountState(1)),
builder: (context, state) {
return Container(...省略業(yè)務(wù)代碼)
},
)
總結(jié)
bloc 庫(kù)中引用了provider 等三方庫(kù)。基于InheritedWidget實(shí)現(xiàn)了數(shù)據(jù)共享能力。本篇文章,小轟只為演示Bloc核心的處理思想。詳細(xì)請(qǐng)查閱Bloc源碼。
擴(kuò)展
InheritedProvider 實(shí)現(xiàn)數(shù)據(jù)共享 Bloc同時(shí)add兩次只響應(yīng)一次問(wèn)題處理
以上就是flutter Bloc 實(shí)現(xiàn)原理示例解析的詳細(xì)內(nèi)容,更多關(guān)于flutter Bloc 實(shí)現(xiàn)原理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android編程實(shí)現(xiàn)應(yīng)用程序開(kāi)機(jī)自啟動(dòng)的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)應(yīng)用程序開(kāi)機(jī)自啟動(dòng)的方法,涉及Android權(quán)限控制及廣播操作相關(guān)技巧,需要的朋友可以參考下2017-02-02
Android 自定義dialog的實(shí)現(xiàn)代碼
這篇文章主要介紹了Android 自定義dialog的實(shí)現(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下2017-03-03
android自定義控件實(shí)現(xiàn)簡(jiǎn)易時(shí)間軸(1)
這篇文章主要為大家詳細(xì)介紹了android自定義控件實(shí)現(xiàn)簡(jiǎn)易時(shí)間軸,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01
Android利用廣播接收器實(shí)現(xiàn)自動(dòng)填充短信驗(yàn)證碼
這篇文章主要為大家詳細(xì)介紹了Android利用廣播接收器實(shí)現(xiàn)自動(dòng)填充短信驗(yàn)證碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12
如何使用SurfaceView實(shí)現(xiàn)魚(yú)兒游動(dòng)動(dòng)畫(huà)
這篇文章主要教大家如何使用SurfaceView實(shí)現(xiàn)魚(yú)兒游動(dòng)動(dòng)畫(huà),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-04-04
Android使用AIDL實(shí)現(xiàn)兩個(gè)App間通信
這篇文章主要為大家詳細(xì)介紹了Android使用AIDL實(shí)現(xiàn)兩個(gè)App間通信,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-04-04
Android開(kāi)發(fā)實(shí)現(xiàn)的標(biāo)準(zhǔn)體重計(jì)算器功能示例
這篇文章主要介紹了Android開(kāi)發(fā)實(shí)現(xiàn)的標(biāo)準(zhǔn)體重計(jì)算器功能,結(jié)合實(shí)例形式分析了Android體重計(jì)算器的界面布局與功能實(shí)現(xiàn)相關(guān)操作技巧,需要的朋友可以參考下2017-12-12
Kotlin自定義實(shí)現(xiàn)支付密碼數(shù)字鍵盤(pán)的方法實(shí)例
這篇文章主要給大家介紹了關(guān)于Kotlin如何自定義實(shí)現(xiàn)支付密碼數(shù)字鍵盤(pán)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-07-07

