flutter_bloc 是實現了 BLoC 模式的第三方庫,可讓你很方便的使用 BLoC 模式開發 Flutter 應用。 git
Hi,你們好!我興奮的宣佈 flutter_bloc 發佈了最新的版本 v0.19.0,其中包含了社區要求的幾個特性,最重要的是提高了開發體驗和減小模板代碼。github
在介紹更新的特性以前,我想先感謝社區裏那些反饋使用體驗、建立 PR、和提 isuues 的人,若是沒有大家的共享的話,咱們很難實現這些新特性。c#
廢話很少說,如今讓咱們看看更新了哪些新特性!bash
在此以前,爲了初始化和回收 bloc,通常都會使用 StatefulWidget 來建立 bloc,由於 StatefulWidget 相比 StatelessWidget 自帶生命週期。可是這也致使了許多模板代碼,並且也會帶來一些問題,例如很容易忘記釋放 bloc 或者在 build 方法裏初始化 bloc。爲了解決這些問題,社區裏有人甚至建立了插件,如 flutter_bloc_extensions 。我很高興的宣佈,這些的反饋已經被採納了,如今 BlockProvider
已經能夠自動的釋放 blocs。架構
BlockProvider
如今有兩種使用方法。less
第一種方法是使用默認的構造函數:ide
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
builder: (BuildContext context) => MyBloc(),
child: MyChild(),
);
}
}
複製代碼
在此以前,你只能這麼寫:函數
class MyWidget extends StatefulWidget {
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
MyBloc _myBloc;
@override
void initState() {
super.initState();
_myBloc = MyBloc();
}
@override
Widget build(BuildContext context) {
return BlocProvider(
bloc: _myBloc,
child: MyChild(),
);
}
@override
void dispose() {
_myBloc.dispose();
super.dispose();
}
}
複製代碼
你能夠看到,在此以前,須要使用 StatefulWidget 來寫 bloc,但如今只須要使用 StatelessWidget 就能夠了,實現 bloc 的代碼量大幅減小,並且會自動釋放 bloc,因此不用擔憂 bloc 的釋放問題。ui
第二種方法是使用 BlocProvider
的 value
構造函數:spa
Navigator.of(context).push(
MaterialPageRoute<MyPage>(
builder: (context) {
return BlocProvider.value(
value: BlocProvider.of<MyBloc>(context),
child: MyPage(),
);
},
),
);
複製代碼
在上面的例子中,把一個已經存在的 MyBloc
實例給 MyPage
使用,MyPage
是一個新頁面,使用 Navigator
打開。在這個例子裏,咱們要爲 MyPage
提供一個已經存在的 MyBloc
實例,而且不但願釋放 MyBloc
當 MyPage
頁面關閉的時候,由於還有其餘地方在使用 MyBloc
。因此,咱們可使用 BlocProvider
的 value
構造函數爲 Widget 提供一個已經存在的 bloc 而且不會自動釋放。能夠點擊 route_access_recipe 查看更多。
總結一下,若是你要建立一個新的 bloc 給子樹使用,就可使用 BlocProvider
的默認構造函數來建立 bloc 實例,會有自動釋放 bloc 的功能。可是若是隻是要給子樹提供一個已經存在的 bloc 實例,這個時候就不須要自動釋放 bloc 的功能,因此使用 BlocProvider
的 value
構造函數。想要釋放 bloc 的話,就在建立 bloc 的地方釋放。
你如今就不須要使用 StatefulWidget
來管理你的 blocs 了。
MultiBlocProvide
的功能是把多個 BlocProvider
合併到一塊兒。
MultiBlocProvide
由於消除了多個 BlocProvider
的嵌套,因此提升了代碼的可讀性。
在此以前,多個 BlocProvider
是這麼寫的:
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider<BlocA>(
builder: (BuildContext context) => BlocA(),
child: BlocProvider<BlocB>(
builder: (BuildContext context) => BlocB(),
child: BlocProvider<BlocC>(
builder: (BuildContext context) => BlocC(),
child: ChildA(),
)
),
);
}
}
複製代碼
有了 MultiBlocProvide
,就能夠這麼寫:
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider<BlocA>(
builder: (BuildContext context) => BlocA(),
),
BlocProvider<BlocB>(
builder: (BuildContext context) => BlocB(),
),
BlocProvider<BlocC>(
builder: (BuildContext context) => BlocC(),
),
],
child: ChildA(),
);
}
}
複製代碼
在上面的例子裏,咱們爲 ChildA
提供了 BlocA
,BlocB
,BlocC
三個 bloc。使用 MultiBlocProvider
能夠無需額外的嵌套,可讓咱們的代碼更好讀。
Repository Provider
是新引進來的 provider,專門用於在 widget 樹中處理 repositories, repositories 用於處理數據請求,相似於 Redux 中的 Middleware。想要知道 repository 是什麼和怎麼用的,能夠點擊這裏查看。
從架構上看,repository 是一個或多個 data providers 的封裝,而且負責與 bloc 通訊。因此,在整個 Widget 樹裏能訪問 repositories 是很是重要的,隨着最近的更新,這個功能很容易就能實現。
咱們可使用 RepositoryProvider
默認的構造函數建立和提供 repository:
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return RepositoryProvider(
builder: (context) => MyRepository(),
child: MyChild(),
);
}
}
class MyChild extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
builder: (context) => MyBloc(RepositoryProvider.of<MyRepository>(context)),
child: MyOtherChild(),
);
}
}
複製代碼
在上面的例子中,咱們爲 MyChild
及其子樹 建立了 MyRepository
的實例。而後在接下來的 Widget 樹裏建立的 MyBloc
(MyBloc
依賴 MyRepository
) 可使用 RepositoryProvider.of
訪問 MyRepository
的實例。你會發現 MyRepository
的 API 和 BlocProvider
很是像,這樣的話就會更加容易使用。
MultiRepositoryProvider
的功能是把多個 RepositoryProvider
合併到一塊兒。
MultiRepositoryProvider
由於消除了多個 RepositoryProvider
的嵌套,因此提升了代碼的可讀性。
在此以前,多個 RepositoryProvider
是這麼寫的:
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return RepositoryProvider<RepositoryA>(
builder: (context) => RepositoryA(),
child: RepositoryProvider<RepositoryB>(
builder: (context) => RepositoryB(),
child: RepositoryProvider<RepositoryC>(
builder: (context) => RepositoryC(),
child: ChildA(),
)
)
);
}
}
複製代碼
有了 MultiRepositoryProvider
,就能夠這麼寫:
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiRepositoryProvider(
providers: [
RepositoryProvider<RepositoryA>(
builder: (context) => RepositoryA(),
),
RepositoryProvider<RepositoryB>(
builder: (context) => RepositoryB(),
),
RepositoryProvider<RepositoryC>(
builder: (context) => RepositoryC(),
),
],
child: ChildA(),
);
}
}
複製代碼
在上面的例子裏,咱們爲 ChildA
提供了 RepositoryA
,RepositoryB
,RepositoryC
。使用 MultiRepositoryProvider
能夠無需額外的嵌套,可讓咱們的代碼更好讀。
你可能注意到,新的 BlocProvider
和 RepositoryProvider
的 API 和 Provider 很像。v0.19.0 的最大更新就是底層使用了 Provider,這樣開發者就能夠擁有一個具備一致 API 的依賴注入庫。在這裏特別感謝 Remi Rousselet 的反饋和耐心。
flutter_bloc 還會繼續吸取接納其餘的 providers(由於 flutter_bloc 會接受社區裏的其餘反饋),可是咱們很是激動在底層使用 Provider,這樣的話咱們就不須要使用以前 咱們本身的 InheritedWidget 的封裝,不須要本身來維護,而是直接享受到 Provider 將來更新帶來的新特性。
你能夠查看咱們完整的 change_log 來查看更多的信息。