[譯]flutter_bloc 最新版本 0.19.0 的最新功能

flutter_bloc 是實現了 BLoC 模式的第三方庫,可讓你很方便的使用 BLoC 模式開發 Flutter 應用。 git

Hi,你們好!我興奮的宣佈 flutter_bloc 發佈了最新的版本 v0.19.0,其中包含了社區要求的幾個特性,最重要的是提高了開發體驗和減小模板代碼。github

在介紹更新的特性以前,我想先感謝社區裏那些反饋使用體驗、建立 PR、和提 isuues 的人,若是沒有大家的共享的話,咱們很難實現這些新特性。c#

廢話很少說,如今讓咱們看看更新了哪些新特性!bash

BlocProvider 的改進

在此以前,爲了初始化和回收 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

第二種方法是使用 BlocProvidervalue 構造函數: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 實例,而且不但願釋放 MyBlocMyPage 頁面關閉的時候,由於還有其餘地方在使用 MyBloc。因此,咱們可使用 BlocProvidervalue 構造函數爲 Widget 提供一個已經存在的 bloc 而且不會自動釋放。能夠點擊 route_access_recipe 查看更多。

總結一下,若是你要建立一個新的 bloc 給子樹使用,就可使用 BlocProvider 的默認構造函數來建立 bloc 實例,會有自動釋放 bloc 的功能。可是若是隻是要給子樹提供一個已經存在的 bloc 實例,這個時候就不須要自動釋放 bloc 的功能,因此使用 BlocProvidervalue 構造函數。想要釋放 bloc 的話,就在建立 bloc 的地方釋放。

你如今就不須要使用 StatefulWidget 來管理你的 blocs 了。

MultiBlocProvide(以前是 BlocProviderTree)

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 (以前是 ImmutableProvider)

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 (過去是 ImmutableProviderTree)

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 能夠無需額外的嵌套,可讓咱們的代碼更好讀。

集成 Provider

你可能注意到,新的 BlocProviderRepositoryProvider 的 API 和 Provider 很像。v0.19.0 的最大更新就是底層使用了 Provider,這樣開發者就能夠擁有一個具備一致 API 的依賴注入庫。在這裏特別感謝 Remi Rousselet 的反饋和耐心。

flutter_bloc 還會繼續吸取接納其餘的 providers(由於 flutter_bloc 會接受社區裏的其餘反饋),可是咱們很是激動在底層使用 Provider,這樣的話咱們就不須要使用以前 咱們本身的 InheritedWidget 的封裝,不須要本身來維護,而是直接享受到 Provider 將來更新帶來的新特性。

你能夠查看咱們完整的 change_log 來查看更多的信息。

相關文章
相關標籤/搜索