Flutterでblocパターンを実装する際に便利な blocライブラリの自分用メモ
まだ実装はしてないので、間違っているところが多いと思います。
Blocライブラリ → https://bloclibrary.dev/#/
Blocパターンとは → https://qiita.com/kabochapo/items/8738223894fb74f952d3
flutter_bloc 3.0.0 → https://pub.dev/packages/flutter_bloc
BlocProvider
基本
複数のサブツリーに指定したblocを提供する。
widget内で使用する場合は、BlocProvider.of<T>(context)
でblocを利用する。ただこのままblocの値をwidgetに使っても、値が変更された時にwidgetはリビルドされないので注意する。値の変更をwidgetに反映するには、BlocBuilderを使用する。
BlocProvider(
create: (BuildContext context) => BlocA(),
child: ChildA(),
);
上記はBlocAを新しく作成し、childAのツリー内に渡している。
新しいblocではなく、既存のBlocをwidgetツリーの新しいルートで利用するには以下のようにする。
BlocProvider.value(
value: BlocProvider.of<BlocA>(context),
child: ScreenA(),
);
MultiBlocProvider
上で述べた方法だと、Blocが複数あるときに複雑なネストが生じる。
BlocProvider<BlocA>(
create: (BuildContext context) => BlocA(),
child: BlocProvider<BlocB>(
create: (BuildContext context) => BlocB(),
child: BlocProvider<BlocC>(
create: (BuildContext context) => BlocC(),
child: ChildA(),
)
)
)
これでは読みにくいので、MultiProvider
を使う。MultiProvider
は上のような複数のBlocProvider
を1つにまとめてくれる。
MultiBlocProvider(
providers: [
BlocProvider<BlocA>(
create: (BuildContext context) => BlocA(),
),
BlocProvider<BlocB>(
create: (BuildContext context) => BlocB(),
),
BlocProvider<BlocC>(
create: (BuildContext context) => BlocC(),
),
],
child: ChildA(),
)
ブロックアクセス
widgetツリー全体でブロックにアクセスする方法 →
https://bloclibrary.dev/#/recipesflutterblocaccess
ローカルアクセス、ルートアクセス、グローバルアクセスの3つのシナリオについて記載されている。
ここでは、ユーザー情報の共有に使えそうなグローバルアクセスについて見ていく。
void main() => runApp(App());
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (BuildContext context) => Bloc(), //グローバルに使いたいBloc
child: MaterialApp(
title: 'demo',
home: Page(),
),
);
}
}
MaterialAppをラップすることで、Blocのインスタンスをグローバルにアクセス可能にする。
widget全体で使いそうなユーザー情報やログイン情報のblocはここで作成する。
BlocBuilder
blocの状態が変わったら、widgetをリビルドする。
BlocLister
Blocの状態が変わったら、Blocを呼び出す。widgetはリビルドされない。
body: Center(
child: BlocListener<WeatherBloc, WeatherState>(
listener: (context, state) {
if (state is WeatherLoaded) {
BlocProvider.of<ThemeBloc>(context).add(
WeatherChanged(condition: state.weather.condition),
);
_refreshCompleter?.complete();
_refreshCompleter = Completer();
}
}
)
「Flutter Weather Tutorial」: https://bloclibrary.dev/#/flutterweathertutorial
上のコードは「Flutter Weather Tutorial」からの引用である。
BlocBuilder
と異なり、変更されたstateの値を処理に利用するだけで、widgetのリビルドは行わない。