私はBLoCパターンに従ってストリームをサブスクライブし、ビルドメソッドの状態変化に対応しています。データが読み込まれたら、画面を閉じます。
_ @override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Bloc'),
),
body: SafeArea(
child: StreamBuilder<UserState>(
stream: _userBloc.user,
initialData: UserInitState(),
builder: (context, snapshot) {
if (snapshot.data is UserInitState) {
return _buildInit();
}
if (snapshot.data is UserDataState) {
Navigator.pop(context, true);
return Container();
}
if (snapshot.data is UserLoadingState) {
return _buildLoading();
}
},
),
),
);
}
_
Navigator.pop(context, true);
メソッドでbuild()
を実行すると、次のようになります。
_I/flutter ( 4360): ══╡ EXCEPTION CAUGHT BY ANIMATION LIBRARY ╞═════════════════════════════════════════════════════════
I/flutter ( 4360): The following assertion was thrown while notifying status listeners for AnimationController:
I/flutter ( 4360): setState() or markNeedsBuild() called during build.
I/flutter ( 4360): This Overlay widget cannot be marked as needing to build because the framework is already in the
I/flutter ( 4360): process of building widgets. A widget can be marked as needing to be built during the build phase
I/flutter ( 4360): only if one of its ancestors is currently building. This exception is allowed because the framework
I/flutter ( 4360): builds parent widgets before children, which means a dirty descendant will always be built.
I/flutter ( 4360): Otherwise, the framework might not visit this widget during this build phase.
_
BLoCパターンでそのようなケースを処理する正しい方法は何ですか?
私が思いついた解決策の1つは、initState()
でストリームのリスニングを開始することです。この場合、2人のサブスクライバーがいるため、ストリームをbroadcast()
する必要があります。
これに対するより良い解決策はありますか?
次の3つの解決策が考えられます。
1)ウィジェットを再構成するのが最善のようです。私が見る限りでは、「ロード画面」が必要です。これが別のウィジェットではなく、独自のナビゲーション項目である必要がある理由はわかりません。
つまり。 StreamBuilder
をプッシュできますか?レベルアップするので、あなたのビルダーメソッドは次のようになります:
_if (!snapshot.hasData) {
return LoadingScreen(snapshot);
}
// Whatever you do with your data.
_
2)私は個人的にStatefulWidget
を作成し、initState()
でストリームを手動でリッスンし、setState()
を手動で呼び出すと思います。 StreamBuilder
は不要
3)クレイジーな回避策として、おそらくビルダーでFuture(() { Navigator.of(context).pop(); });
を使用できます。 (ビルダーではなく、context
メソッドのbuild
を使用する必要がある可能性があります。しかし、とにかくその解決策はお勧めしません)