在上一篇文章中我們了解到Stream及響應(yīng)式編程的相關(guān)概念,本文著重介紹在引入 RxDart 三方庫(kù)后,不同Subject在實(shí)際開發(fā)中的應(yīng)用場(chǎng)景。

成都創(chuàng)新互聯(lián)專業(yè)為企業(yè)提供點(diǎn)軍網(wǎng)站建設(shè)、點(diǎn)軍做網(wǎng)站、點(diǎn)軍網(wǎng)站設(shè)計(jì)、點(diǎn)軍網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)與制作、點(diǎn)軍企業(yè)網(wǎng)站模板建站服務(wù),10多年點(diǎn)軍做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。
先附上演示項(xiàng)目代碼: flutter_movie
RxDart 是基于 ReactiveX 標(biāo)準(zhǔn)API的Dart版本實(shí)現(xiàn),由Dart標(biāo)準(zhǔn)庫(kù)中Stream擴(kuò)展而成。因此,RxDart與Dart的相關(guān)術(shù)語(yǔ)稍有區(qū)別:
Observable 等同于 Stream , Subject 等同于 StreamController ,前者均由后者繼承而來(lái)。
不同于Dart,RxDart提供了三種StreamController的變體來(lái)應(yīng)用到不同的場(chǎng)景:
PublishSubject是最普通的廣播StreamController,和StreamController唯一的區(qū)別是它返回對(duì)象是Observable,而StreamController返回的是Stream。
PublishSubject PublishSubject
從圖中可以了解到,listener只能監(jiān)聽到訂閱之后的事件。
示例代碼:
BehaviorSubject也是廣播StreamController,和PublishSubject的區(qū)別是它會(huì)額外返回訂閱前的最后一次事件。
BehaviorSubject BehaviorSubject
示例代碼:
ReplaySubject也是廣播StreamController,從字面上可以了解到它可以回放已經(jīng)消失的事件。
ReplaySubject ReplaySubject
示例代碼:
上文提到 StreamBuilder 作為Flutter中根據(jù)Stream生成Widget的便利工具,這里結(jié)合Subject來(lái)一起使用。
tab_bar.dart - 01 tab_bar.dart - 01 tab_bar.dart - 02 tab_bar.dart - 02
以上代碼實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的TabBar(或Segment),該Widget被定義成為一個(gè)StatefulWidget(因?yàn)樗邳c(diǎn)擊交互后有更新高亮索引的需求)。
在 build 函數(shù)內(nèi)部我們就使用了StreamBuilder來(lái)構(gòu)建UI,它監(jiān)聽的數(shù)據(jù)源為BLoc的 tabList ,在builder閉包內(nèi)部才是實(shí)際的UI構(gòu)建代碼。
tab_bloc.dart tab_bloc.dart
至于 tab_bloc.dart 則更加簡(jiǎn)單,他從構(gòu)造函數(shù)接收一個(gè)字符串類型的List,然后使用ReplaySubject包裝數(shù)據(jù),
同時(shí)暴露出stream類型的對(duì)象 tabList 供外部訂閱(即 tab_bar.dart 中第44行代碼中的stream)。
最后,我們來(lái)看看完整的調(diào)用流程。
main.dart main.dart
在 main.dart 第30~50行代碼中,我們使用了 BlocProvider 來(lái)管理bloc(對(duì)于BlocProvider深入了解可以參考上一篇文章的相關(guān)部分),
provider包裹的是整個(gè) HomePage 這使得在page內(nèi)部任何地方訪問(wèn)到bloc成為可能。
home.dart home.dart
在 home.dart 第38,39行代碼中,我們使用provider獲取bloc,并完成對(duì)TabBar的初始化。
更進(jìn)一步,上篇文章提到的StreamTransformer可以對(duì)Stream進(jìn)行相應(yīng)的處理,同樣的,RxDart中也支持類似的操作,它們被稱為 操作符 。
search_list_bloc.dart search_list_bloc.dart
在上述稍顯復(fù)雜的示例中,實(shí)現(xiàn)了基本的分頁(yè)搜索功能。其中13~17行代碼完成搜索索引位置監(jiān)聽前的處理,包括 采樣 (按時(shí)間采樣的緩存操作)、過(guò)濾、去重操作。
換句話說(shuō),在最終監(jiān)聽到start之前,我們都可以對(duì)Observable對(duì)象進(jìn)行一系列地處理以達(dá)到數(shù)據(jù)使用方的需求。
相信很多人對(duì)于Flutter系列的開篇以響應(yīng)式編程為主題表示有點(diǎn)異議,但谷歌官方推行這一架構(gòu)必然有其合理性,無(wú)論是狀態(tài)管理上還是Dart的原生支持上而言。
在學(xué)習(xí)新技術(shù)時(shí)不僅要學(xué)習(xí)語(yǔ)言的語(yǔ)法,更要理解其架構(gòu)思想(新瓶裝舊酒,F(xiàn)lutter和Dart是新瓶,響應(yīng)式編程的思想是舊酒),將思維轉(zhuǎn)變過(guò)來(lái)才能更加快速地獲得新技術(shù)為我們帶來(lái)的便利性。
后續(xù)的文章將圍繞文章開頭的demo項(xiàng)目進(jìn)行展開,盡請(qǐng)期待~
Flutter狀態(tài)管理系列:
Flutter狀態(tài)管理(一):ScopedModel
Flutter狀態(tài)管理(二):Provider
Flutter狀態(tài)管理(三):BLoC(Business Logic Component)
Flutter狀態(tài)管理(四):ReactiveX之RxDart
Flutter狀態(tài)管理(五):Redux
有做過(guò)H5前端開發(fā)的朋友應(yīng)該很早就接觸過(guò)這個(gè),Redux在React/VUE中,與在Flutter/Dart中概念一樣,沒有任何區(qū)別;唯一的區(qū)別只是使用上的不同。
它主要由三部分組成:
下圖是一個(gè)完整的數(shù)據(jù)觸發(fā)及更新流程:
我們看到上面整個(gè)數(shù)據(jù)流,都是單向的,由View發(fā)起,最后到View的更新;
為啥這樣設(shè)計(jì)?
小節(jié)二介紹了Redux最基本的原理,但是,如何用Redux來(lái)做一些異步操作,比如:加載數(shù)據(jù)、請(qǐng)求API等?這里就引出來(lái)了Redux的中間件(Middleware),中間件能夠讓我們使得action在到達(dá)reducer之前,做些其它“動(dòng)作”!有了中間件,我們不但可以請(qǐng)求API,還可以改變action,使得分發(fā)到其它reducer中去;
上圖是有Middleware的流程圖。
Redux在Flutter中的使用與在JavaScript中的使用方式稍微有點(diǎn)不同,為啥?
因?yàn)镴avaScript是弱類型語(yǔ)言,而Dart是強(qiáng)類型語(yǔ)言,這就使得在JS中每個(gè)reducer可以獨(dú)立管理,而在Flutter中需要由一個(gè)大對(duì)象來(lái)管理!
無(wú)論在JS中還是在Flutter中,通常都將action、reducer、store各自建一目錄,放在redux目錄下,目錄結(jié)構(gòu)如下:
ReduxPage在build中,也可以直接用StoreBuilder(參考ReduxPage2中寫法),因?yàn)镾toreBuilder也是InheritedWidget。
正因?yàn)镽edux在Flutter中與在JS中不同,因此,在Flutter中,建議:
初始化問(wèn)題:這邊初始化是在bloc里,直接在構(gòu)造方法里面賦初值的,state中一旦變量多了,還是這么寫,會(huì)感覺極其難受,不好管理。需要優(yōu)化
如果進(jìn)行一個(gè)頁(yè)面,需要進(jìn)行復(fù)雜的運(yùn)算或者請(qǐng)求接口后,才能知曉數(shù)據(jù),進(jìn)行賦值,這里肯定需要一個(gè)初始化入口,初始化入口需要怎樣去定義呢?
首先對(duì)state進(jìn)行優(yōu)化,新增倆個(gè)方法:init()和clone()
init():這里初始化統(tǒng)一用init()方法去管理。
clone():這邊克隆方法,是非常重要的,一旦變量達(dá)到倆位數(shù)以上,就能深刻體會(huì)該方法是多么的重要。
定義一個(gè)與初始化state相對(duì)應(yīng)的init()初始化方法
這增加了初始化方法,請(qǐng)注意,如果需要進(jìn)行異步請(qǐng)求,同時(shí)需要將相關(guān)邏輯提煉一個(gè)方法,咱們?cè)谶@里配套Future和await就能解決在異步場(chǎng)景下同步數(shù)據(jù)問(wèn)題.
這里使用了克隆方法,可以發(fā)現(xiàn),我們只要關(guān)注自己需要改變的變量就行了,其它的變量都在內(nèi)部賦值好了,我們不需要去關(guān)注;這就大大的便捷了頁(yè)面中有很多變量,只需要變動(dòng)一倆個(gè)變量的場(chǎng)景。
view層增加了個(gè)初始化事件。初始化操作直接在創(chuàng)建的時(shí)候,在XxxBloc上使用add()方法就行了,就能起到進(jìn)入頁(yè)面,初始化一次的效果。
bloc的思想
觀察者模式的思想;觀察者(回調(diào)刷新控件)和被觀察者(產(chǎn)生相應(yīng)事件,添加事件,去通知觀察者),bloc層是處于觀察者和被觀察者中間的一層,我們可以在bloc里面搞業(yè)務(wù),搞邏輯,搞網(wǎng)絡(luò)請(qǐng)求;拿到Event事件傳遞過(guò)來(lái)的數(shù)據(jù),把處理好的、符合要求的數(shù)據(jù)返回給view層的觀察者就行了。
1、繼承SingleChildStatelessWidget,就是一個(gè)widget,通過(guò)create 傳入一個(gè)Bloc對(duì)象
1、Bloc繼承自BlocBase,BlocBase中創(chuàng)建了StreamController對(duì)象,為多訂閱對(duì)象
其中onCounterEvent((event, emit)為初始化創(chuàng)建_eventController監(jiān)聽
2、Bloc中創(chuàng)建_eventController,為事件通知
3、BlocBase創(chuàng)建_stateController,為狀態(tài)刷新通知
4、add方法是執(zhí)行廣播通知
5、處理完數(shù)據(jù)之后執(zhí)行emit()方法,其中emit方法是stateController廣播
1、 BlocBuilder繼承自BlocBuilderBase,_BlocBuilderBaseState中build方法返回的是BlocListener
2、BlocListener繼承BlocListenerBase,_BlocListenerBaseState中_subscribe()添加監(jiān)聽stateController廣播通知
當(dāng)前題目:flutterbloc,flutterbloc add 無(wú)效
文章位置:http://chinadenli.net/article25/dsidgci.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站策劃、動(dòng)態(tài)網(wǎng)站、云服務(wù)器、網(wǎng)站導(dǎo)航、外貿(mào)建站、品牌網(wǎng)站設(shè)計(jì)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)