flutter Bloc 更新后事件同步與異步詳解
前言
最近,小轟參與了公司 flutter 項(xiàng)目關(guān)于 Dart 2.0 的空安全升級(jí)工作。我們升級(jí)了所有依賴的三方庫,其中就包括有 Bloc 庫。作為一款使用率頗高的狀態(tài)管理框架, Bloc 在版本迭代中進(jìn)行了少許結(jié)構(gòu)和細(xì)節(jié)的優(yōu)化,下面是小轟對(duì)于 Bloc 新版本的使用總結(jié)。
使用方式
小轟使用的 Bloc 版本如下
flutter_bloc: ^7.3.1
通過最簡單的例子來學(xué)習(xí)新知識(shí)
- 創(chuàng)建一個(gè)包含 加 減 操作的頁面,使用 bloc 來操作 自增 自減 事件。
class _TestBlocPageState extends State<TestBlocPage> { late TestDartBloc _bloc; @override void initState() { super.initState(); _bloc = TestDartBloc(TestDartState(0)); } @override Widget build(BuildContext context) { return BlocBuilder<TestDartBloc, TestDartState>( bloc: _bloc, builder: (context, state) { return Column( children: [ //顯示當(dāng)前的數(shù)字結(jié)果 Text(state.num.toString()), TextButton( onPressed: () { //進(jìn)行自增操作 _bloc.add(IncreaseEvent()); }, child: Text('add')), TextButton( onPressed: () { //進(jìn)行自減操作 _bloc.add(ReduceEvent()); }, child: Text('reduce')), ], ); }, ); } }
Bloc 中 state 和 event 模型定義如下
part of 'test_dart_bloc.dart'; /// Bloc state class TestDartState { int num = 0; TestDartState(this.num); }
part of 'test_dart_bloc.dart'; /// Bloc event @immutable abstract class TestDartEvent {} //自增事件 class IncreaseEvent extends TestDartEvent{} //自減事件 class ReduceEvent extends TestDartEvent{}
創(chuàng)建 Bloc ,重寫 mapEventToState 接收事件流轉(zhuǎn)狀態(tài)流
import 'dart:async'; import 'package:flutter_bloc/flutter_bloc.dart'; part 'test_dart_event.dart'; part 'test_dart_state.dart'; class TestDartBloc extends Bloc<TestDartEvent, TestDartState> { TestDartBloc(TestDartState state) : super(state); @override Stream<TestDartState> mapEventToState(TestDartEvent event) async* { if (event is IncreaseEvent) { await Future.delayed(Duration(seconds: 10)); yield TestDartState(state.num + 1); } else if (event is ReduceEvent) { yield TestDartState(state.num - 1); } } }
好了,直接運(yùn)行如上代碼,我們的demo就能完整的跑起來。但,以上的寫法和低版本的 Bloc 完全一致,在經(jīng)歷高版本迭代后,Bloc 到底做了哪些優(yōu)化呢?
Bloc 新形態(tài)用法
小轟在源碼里看到,重寫 mapEventToState 的使用方式已經(jīng)被棄用了,會(huì)在將來的某個(gè)版本中徹底刪除該 API
/// **@Deprecated - Use on<Event> instead. Will be removed in v8.0.0** /// /// Must be implemented when a class extends [Bloc]. /// [mapEventToState] is called whenever an [event] is [add]ed /// and is responsible for converting that [event] into a new [state]. /// [mapEventToState] can `yield` zero, one, or multiple states for an event. @Deprecated('Use on<Event> instead. Will be removed in v8.0.0') Stream<State> mapEventToState(Event event) async* {}
新用法推薦使用 on 來進(jìn)行事件注冊(cè),我們將上面demo中的 bloc 進(jìn)行寫法改造:
class TestDartBloc extends Bloc<TestDartEvent, TestDartState> { TestDartBloc(TestDartState state) : super(state) { init(); } void init() { on<IncreaseEvent>((event, emit) async { await Future.delayed(Duration(seconds: 10)); emit(TestDartState(state.num + 1)); }); on<ReduceEvent>((event, emit) { state.num - 1; emit(state); }); } }
替換代碼后運(yùn)行demo,直接成功。
事件隊(duì)列的阻塞屬性?
目前最新版本的 Bloc 同時(shí)支持 on 與 mapEventToState 兩種寫法,那么這兩種寫法有實(shí)際區(qū)別嗎?
小轟在使用老版本(空安全之前)bloc 時(shí)總結(jié)過一篇文章 聊聊 Bloc event 的隊(duì)列屬性。
在 bloc 的 mapEventToState 方法中,event 隊(duì)列是一個(gè)阻塞性隊(duì)列,先進(jìn)先出,只有當(dāng)上一個(gè)事件消費(fèi)完畢后,才會(huì)響應(yīng)隊(duì)列中的下一個(gè)事件。
如上demo( mapEventToState 方式): 自增事件中模擬耗時(shí)了10s,當(dāng)依次點(diǎn)擊 自增 和 自減 按鈕后,由于事件隊(duì)列的阻塞特性,自增事件消費(fèi)10秒后,自減事件才會(huì)被 mapEventToState 響應(yīng)。
那么,這個(gè)特性在 bloc 迭代新版本后還存在嗎?在最新版本的bloc中,小轟通過demo測試得出結(jié)論:
- 當(dāng)使用 mapEventToState 方式進(jìn)行事件捕獲時(shí),event 隊(duì)列 保持 阻塞 特性。
- 而使用 on 方式進(jìn)行注冊(cè)監(jiān)聽時(shí),event 隊(duì)列 默認(rèn)是異步非阻塞的,是互不干擾的。如果把 bloc 當(dāng)作事件總線來使用,小轟認(rèn)為 異步非阻塞 這樣的設(shè)計(jì)更為合理。
提問:如果想使用 on 的方式進(jìn)行注冊(cè),還想事件隊(duì)列保證順序執(zhí)行即保持阻塞特性,應(yīng)該怎么辦呢? 解答:使用 自定義 transformer,這樣就實(shí)現(xiàn)了事件同步隊(duì)列。
on<IncreaseEvent>((event, emit) async { await Future.delayed(Duration(seconds: 10)); emit(TestDartState(state.num + 1)); }, transformer: (events, mapper) => events.asyncExpand(mapper), );
參考鏈接: pub.dev/packages/bl…
以上就是flutter Bloc 更新后事件同步與異步詳解的詳細(xì)內(nèi)容,更多關(guān)于flutter Bloc 更新事件同步異步的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Apache?Cordova?Android原理應(yīng)用實(shí)例詳解
這篇文章主要為大家介紹了Apache?Cordova?Android原理應(yīng)用實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11Android 實(shí)現(xiàn)滑動(dòng)的六種方式
這篇文章主要給大家分享的是Android 實(shí)現(xiàn)滑動(dòng)的六種方式,分別是layout、scrollBy、offsetLeftAndRight offsetTopAndButton、LayoutParams、Scroller、平移動(dòng)畫,需要的朋友可以參考一下下面文章的具體內(nèi)容2021-11-11Android實(shí)現(xiàn)EditText控件禁止輸入內(nèi)容的方法(附測試demo)
這篇文章主要介紹了Android實(shí)現(xiàn)EditText控件禁止輸入內(nèi)容的方法,涉及Android針對(duì)EditText控件屬性設(shè)置的相關(guān)技巧,需要的朋友可以參考下2015-12-12Android開發(fā)之自帶下載器DownloadManager的使用示例代碼
本篇文章主要介紹了Android開發(fā)之自帶下載器DownloadManager的使用示例代碼,Android自帶的DownloadManager是一個(gè)很好的下載文件的工具,有興趣的可以了解一下。2017-03-03Android SurfaceView基礎(chǔ)用法詳解
這篇文章主要介紹了Android SurfaceView基礎(chǔ)用法詳解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08Android 選擇相冊(cè)照片并返回功能的實(shí)現(xiàn)代碼
這篇文章主要介紹了Android 從相冊(cè)中選擇照片并返回功能,需要的朋友可以參考下2018-03-03Android中ListView的幾種常見的優(yōu)化方法總結(jié)
Android中的ListView應(yīng)該算是布局中幾種最常用的組件之一,本篇文章主要做了三種優(yōu)化總結(jié),有興趣的可以了解一下。2017-02-02Android onActivityResult和setResult方法詳解及使用
這篇文章主要介紹了Android onActivityResult和setResult方法詳解及使用的相關(guān)資料,這里提供實(shí)例,幫助大家學(xué)習(xí)理解,需要的朋友可以參考下2016-12-12Android實(shí)現(xiàn)透明動(dòng)畫
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)透明動(dòng)畫,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-05-05