Flutter狀態(tài)管理Bloc使用示例詳解
前言
目前Flutter三大主流狀態(tài)管理框架分別是provider、flutter_bloc、getx,三大狀態(tài)管理框架各有優(yōu)劣,本篇文章將介紹其中的flutter_bloc框架的使用,他是bloc設(shè)計(jì)思想模式在flutter上的實(shí)現(xiàn),bloc全程全稱 business logic ,業(yè)務(wù)邏輯的意思,核心思想就是最大程度的將頁(yè)面ui與數(shù)據(jù)邏輯的解耦,使我們的項(xiàng)目可讀性、可維護(hù)性、健壯性增強(qiáng)。
兩種使用模式
首先第一步引入插件:
flutter_bloc: ^8.1.1
引入之后,flutter_bloc使用支持以下兩種模式管理。
Bloc模式,分別有ui層(view)、數(shù)據(jù)層(state)、事件層(event)、邏輯處理層(bloc),適合大型復(fù)雜頁(yè)面使用。這四層結(jié)構(gòu)bloc在源碼處就進(jìn)行了封裝處理,所以我們使用的時(shí)候是必須要分離出來(lái)的,比如event和state是要強(qiáng)制分開(kāi)去寫(xiě)的。這也導(dǎo)致了簡(jiǎn)單頁(yè)面使用此模式復(fù)雜化的問(wèn)題,所以這種模式對(duì)于簡(jiǎn)單頁(yè)面是非常沒(méi)有必要的,但是如果是復(fù)雜頁(yè)面的話,非常建議使用此模式,相信你在處理頁(yè)面數(shù)據(jù)邏輯的時(shí)候會(huì)非常的清晰。
下面我們以計(jì)數(shù)器為例寫(xiě)個(gè)demo,記住bloc模式有四層,且必須分開(kāi),我們建四個(gè)文件分別代表這四層,

數(shù)據(jù)層: 用來(lái)存放數(shù)據(jù),這個(gè)很簡(jiǎn)單。
/// 數(shù)據(jù)層
class DemoState {
// 自增數(shù)字
late int num;
DemoState init() {
// 初始化為0
return DemoState()..num = 0;
}
DemoState clone() {
// 獲取最新對(duì)象
return DemoState()..num = num;
}
}
事件層: 用來(lái)存放頁(yè)面所有事件的地方,比如計(jì)數(shù)器頁(yè)面只有初始化事件和自增事件。
/// 頁(yè)面中所有的交互事件
abstract class DemoEvent {}
/// 初始化事件
class InitEvent extends DemoEvent {}
/// 自增事件
class IncrementEvent extends DemoEvent {}
Bloc邏輯處理層: 處理上方數(shù)據(jù)和事件邏輯的地方,通過(guò)源碼就能發(fā)現(xiàn)作者的意圖,泛型里必須分開(kāi)傳入事件和數(shù)據(jù),也足以說(shuō)明這個(gè)模式的特點(diǎn),就是為復(fù)雜頁(yè)面準(zhǔn)備的。
所以如果寫(xiě)計(jì)數(shù)器的話,你就會(huì)感覺(jué)非常沒(méi)有必要,因?yàn)橛?jì)數(shù)器頁(yè)面很簡(jiǎn)單,但是當(dāng)你的state層里的數(shù)據(jù)非常多且復(fù)雜的時(shí)候,你就能體會(huì)出分開(kāi)的好處了。

代碼:
/// 邏輯處理層 繼承Bloc
class DemoBloc extends Bloc<DemoEvent, DemoState> {
///構(gòu)造方法
DemoBloc() : super(DemoState().init()) {
/// on 注冊(cè)所有事件 on固定寫(xiě)法
on<InitEvent>(_init);
on<IncrementEvent>(_add);
}
/// 私有化邏輯方法 暴露Event事件即可
void _init(InitEvent event, Emitter<DemoState> emit) {
// emit方法,通知更新?tīng)顟B(tài) 類似于 ChangeNotifier的notifyListeners方法。
emit(state.clone());
}
_add(IncrementEvent event, Emitter<DemoState> emit) {
state.num++;
// 調(diào)用emit方法更新?tīng)顟B(tài)
emit(state.clone());
}
}
UI層: UI層只負(fù)責(zé)頁(yè)面的編寫(xiě),而無(wú)需關(guān)心數(shù)據(jù)的生成,根節(jié)點(diǎn)返回BlocProvider,并實(shí)現(xiàn)create方法,返回我們的bloc實(shí)體類。child實(shí)現(xiàn)我們的 UI頁(yè)面。
/// UI層
class BlocNumPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 以下固定寫(xiě)法
return BlocProvider(
create: (BuildContext context) => DemoBloc()..add(InitEvent()),
child: Builder(builder: (context) => _buildPage(context)),
);
}
Widget _buildPage(BuildContext context) {
// 獲取bloc實(shí)例
final bloc = BlocProvider.of<DemoBloc>(context);
return Stack(
children: [
Center(
// 對(duì)于需要更新?tīng)顟B(tài)的組件 外層包裹一個(gè)BlocBuilder,傳入bloc、state
child: BlocBuilder<DemoBloc, DemoState>(
builder: (context, state) {
// 返回具體ui組件
return Text("點(diǎn)擊了${bloc.state.num}次");
},
),
),
Positioned(
bottom: 20,
right: 20,
child: FloatingActionButton(
onPressed: () {
// 調(diào)用add方法觸發(fā)自增事件,
bloc.add(IncrementEvent());
},
child: Icon(Icons.add),
),
)
],
);
}
}
效果:

Cubit模式
Cubit模式,分別有ui層(view)、數(shù)據(jù)層(state)、邏輯處理層(cubit),相較于bloc模式去掉了event層,適合比較簡(jiǎn)單的頁(yè)面。跟bloc模式只是邏輯處理哪里發(fā)生了改變,數(shù)據(jù)層、頁(yè)面ui層代碼一模一樣。
可以看到Cubit模式的邏輯就少了很多代碼,而且是直接處理數(shù)據(jù)即可。通過(guò)源碼,作者意圖也很明顯,只是傳遞了數(shù)據(jù)層。

/// 寫(xiě)邏輯
class CubitCubit extends Cubit<CubitState> {
CubitCubit() : super(CubitState().init());
///自增
void increment() => emit(state.clone()..num = state.num + 1);
}
其他寫(xiě)法跟Bloc是一樣的,就不粘貼了,那看到這有的小伙伴可能就要問(wèn)了,一個(gè)頁(yè)面要?jiǎng)?chuàng)建3、4個(gè)文件,這也太麻煩了吧,高端的程序員往往不會(huì)去寫(xiě)一些重復(fù)性較高的代碼,其實(shí)上面的四個(gè)文件都是可以通過(guò)插件自動(dòng)生成的,這里下面兩個(gè)插件,一個(gè)是官方的,官方的不會(huì)自動(dòng)生成ui層的文件,一個(gè)是小呆呆寫(xiě)的,可以自動(dòng)生成ui層重復(fù)性的代碼文件,兩者區(qū)別不大,推薦小呆呆的,因?yàn)榭梢远嗌梢粋€(gè)文件。

最后
Bloc本質(zhì)上是一種數(shù)據(jù)邏輯和UI解耦思想,上面的演示只是非常非常簡(jiǎn)單的用法,就可以看出作者在源碼層給我們強(qiáng)制性的設(shè)定了非常明確的各個(gè)模型,每個(gè)模型只專心負(fù)責(zé)一個(gè)事情,這樣看起來(lái)一個(gè)頁(yè)面會(huì)非常的清晰,可以說(shuō)Flutter_Bloc是一個(gè)非常適合大型項(xiàng)目使用的狀態(tài)管理框架。
以上就是Flutter狀態(tài)管理Bloc使用示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Flutter狀態(tài)管理Bloc的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android RecyclerView 復(fù)用錯(cuò)亂通用解法詳解
本篇文章主要介紹了Android RecyclerView 復(fù)用錯(cuò)亂通用解法詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-08-08
Android compose氣泡升起和水滴下墜動(dòng)畫(huà)實(shí)現(xiàn)示例
這篇文章主要為大家介紹了Android compose氣泡升起和水滴下墜動(dòng)畫(huà)實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
Android EdText編輯框禁止輸入表情符號(hào)(使用正則表達(dá)式)
這篇文章主要介紹了Android EdText編輯框禁止輸入表情符號(hào)使用正則表達(dá)式,需要的朋友可以參考下2017-06-06
Android自定義UI實(shí)現(xiàn)微信語(yǔ)音
這篇文章主要為大家詳細(xì)介紹了Android自定義UI實(shí)現(xiàn)微信語(yǔ)音的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11
Android-自定義控件之ListView下拉刷新的實(shí)現(xiàn)
本篇文章主要介紹了Android-自定義控件之ListView下拉刷新示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02
Android 判斷SIM卡屬于哪個(gè)移動(dòng)運(yùn)營(yíng)商詳解及實(shí)例
這篇文章主要介紹了Android 判斷SIM卡屬于哪個(gè)移動(dòng)運(yùn)營(yíng)商詳解相關(guān)資料,并附實(shí)例代碼,具有一定參考價(jià)值,需要的朋友可以參考下2016-11-11
Android中Gallery和ImageSwitcher的使用實(shí)例
今天小編就為大家分享一篇關(guān)于Android中Gallery和ImageSwitcher的使用實(shí)例,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-03-03

