題記
—— 執劍天涯,從你的點滴積累開始,所及之處,必精益求精。
Flutter是谷歌推出的最新的移動開發架構。
【x1】微信公衆号的每日提醒 随時随記 每日積累 随心而過 【x2】各種系列的視訊教程 免費開源 關注 你不會迷路 【x3】系列文章 百萬 Demo 随時 複制粘貼 使用 在 Flutter 中可用于異步通信的方案有如下:- Provider ( Provider 異步通信、Provider狀态管理 )
- ValueNotifier 點選檢視詳情
- Stream: StreamController的使用詳情 | StreamBuilder元件的結合使用 StreamBuilder 實作的倒計時進度圓圈
- EventBus (不考慮使用)
-
Bloc [BLoC 異步通信、BlocBuilder的基本使用、BlocProvider的初探
](
https://biglead.blog.csdn.net/article/details/109173443)
1 前言
BloC 全稱是 Business Logic Component(業務邏輯元件),主要作用就是将業務邏輯和UI元件分離開。
在Flutter項目開發中,一般的項目中,會有網絡請求的代碼與Widget建構的UI界面寫一起,随着業務的不斷積累,代碼量也越來越大,維護的複雜度也會随着增加。
BLoC模式可以将Widget建構UI的代碼與業務處理的代碼分離出來,在BLoC模式下的應用程式,一般會有全局的BLoC,每一個頁面也會對應有一個獨立的BLoC。
使用BloC模式,Flutter項目應用裡的所有元件都在一個事件流,其中一部分元件可以訂閱事件,另一部分元件則消費事件
2 BloC 的基本使用
BloC是一種架構模式也是一種程式設計思想,在Flutter中使用BloC時,首先要引入
bloc庫dependencies:
flutter_bloc: ^6.0.6
然後将依賴庫拉取到本地
flutter packages get
在Flutter BloC模式開發中常用元件有BlocBuilder、BlocProvider、BlocListener和BlocConsumer等等。
在這裡使用Bloc模式開發一個時間計時器 運作效果如下圖所示:
首先來看程式入口,在這裡使用到了 BlocProvider ,BlocProvider相當于一個組合者,它将 Bloc 、事件、消費組合在一起,在本文章 第四小節有詳細概述,代碼如下:
///flutter應用程式中的入口函數
void main() => runApp(BlocMainApp());
///應用的根布局
class BlocMainApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
///建構Materia Desin 風格的應用程式
return BlocProvider<CounterBloc>(
create: (context) => CounterBloc(""),
child: MaterialApp(
///Android應用程式中工作列中顯示應用的名稱
title: "配制",
theme: ThemeData(
accentColor: Colors.blue,
///預設是 Brightness.light
brightness: Brightness.light,
),
///預設的首頁面
home: TestBlocTimePage(),
),
);
}
}
對于 TestBlocTimePage 就是 MaterialApp中設定預設顯示的 home 首頁面,是自定義的一個 Widget 頁面,在這裡使用 Scaffold 來建構頁面主體,然後初始化了一個 計時器Timer,代碼如下:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'dart:async';
import 'bloc_time.dart';
///Bloc 初探
class TestBlocTimePage extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _TestABPageState();
}
}
class _TestABPageState extends State {
///計時器
Timer _timer;
@override
void initState() {
super.initState();
///間隔1秒執行時間
_timer= Timer.periodic(Duration(milliseconds: 1000), (timer) {
///發送事件
BlocProvider.of<TimeCounterBloc>(context).add(0);
});
}
@override
void dispose() {
super.dispose();
///取消計時器
_timer.cancel();
}
@override
Widget build(BuildContext context) {
///頁面主體腳手架
return Scaffold(
appBar: AppBar(
title: Text("Bloc "),
),
body:buildBlocBuilder(),
);
}
///代碼清單1-1
/// 通過 BlocBuilder 來消費事件結果
Widget buildBlocBuilder() {
return BlocBuilder<TimeCounterBloc, String>(
builder: (context, time) {
///在這裡 time 就是BloC回傳的資料處理結果
///當然在這裡是一個 String 類型
return Container(
///外邊距
margin: EdgeInsets.only(left: 12,top: 12),
child: Text(
'$time',
style: TextStyle(fontSize: 22.0, color: Colors.red),
),
);
},
);
}
}
在這裡定義的 BlocBuilder,本文第三小節有分析。
定義的 Bloc 角色,代碼如下:
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:intl/intl.dart';
///Bolc 的泛型資料類型
///在這裡 int 代表輸入的事件類型
/// String 代表輸出的資料結果
class TimeCounterBloc extends Bloc<int, String> {
///預設構造
///[initialState]預設的資料
TimeCounterBloc(String initialState) : super(initialState);
///業務邏輯處理 [event] 事件辨別
@override
Stream<String> mapEventToState(int event) async* {
///擷取目前的時間
DateTime dateTime= DateTime.now();
///格式化時間 import 'package:intl/intl.dart';
///需要添加 intl 依賴
String formatTime = DateFormat("HH:mm:ss").format(dateTime);
///發射更新資料
yield formatTime;
}
}
3 BlocBuilder
BlocBuilder與StreamBuilder的作用一樣,用來消費事件結果,就是顯示資料結果,它的建構建構如下:
class BlocBuilder<C extends Cubit<S>, S> extends BlocBuilderBase<C, S> {
/// {@macro bloc_builder}
const BlocBuilder({
Key key,
@required this.builder,
C cubit,
BlocBuilderCondition<S> buildWhen,
}) : assert(builder != null),
super(key: key, cubit: cubit, buildWhen: buildWhen);
... ...
}
builder 參數為必選參數,用來建構消費的 UI 視圖,它需要一個 BlocWidgetBuilder,BlocWidgetBuilder定義如下:
typedef BlocWidgetBuilder<S> = Widget Function(BuildContext context, S state);
BlocWidgetBuilder 的入參數二 state 就是 BloC 中發射的資料。
buildWhen參數,用于向BlocBuilder提供可選的條件,傳回 true,那麼将調用state執行視圖的重新建構,如果傳回false,則不會執行視圖的重建操作。
Widget buildBlocBuilder() {
return BlocBuilder<TimeCounterBloc, String>(
///條件判斷是否更新視圖
/// 參數 previous 上一次的資料
/// 參數 current 目前的資料
buildWhen: (String previous,String current){
print("previous $previous current $current");
return true;
},
///入參 time 為BloC發射的資料
builder: (context, time) {
///在這裡 time 就是BloC回傳的資料處理結果
///當然在這裡是一個 String 類型
return Container(
///外邊距
margin: EdgeInsets.only(left: 12,top: 12),
child: Text(
'$time',
style: TextStyle(fontSize: 22.0, color: Colors.red),
),
);
},
);
}
4 BlocProvider
BlocProvider相當于一個組合者,它将 Bloc 、事件、消費組合在一起,它是一個元件。
可以通過BlocProvider.of (context)向其子級提供bloc,如上述的 add 方法發送事件
BlocProvider.of<TimeCounterBloc>(context).add(0);
5 MultiBlocProvider
MultiBlocProvider是一個用于将多個BlocProvider合并為一個BlocProvider的元件。
MultiBlocProvider(
providers: [
BlocProvider<BlocA>(
create: (BuildContext context) => BlocA(),
),
BlocProvider<BlocB>(
create: (BuildContext context) => BlocB(),
),
BlocProvider<BlocC>(
create: (BuildContext context) => BlocC(),
),
],
child: 子頁面視圖,
)
然後在子頁面中 通過 BlocBuilder 分别引用不同的 Bloc 就可以,小編這也有 Demo
完畢
以小編的性格,要實作百萬Demo随時複制粘貼肯定是需要源碼的
當然以小編的性格,肯定是要有視訊錄制的,目前正在錄制中,你可以關注一下
西瓜視訊 --- 早起的年輕人随後會上傳