![](/img/trans.png)
[英]How to correctly use BlocListener and BlocProvider in Flutter App
[英]How to set correctly the BlocProvider between two different routes (screens)?
我正在為我的應用程序使用Bloc ,但是我做錯了什么,也就是說,提供了在MaterialApp
中創建的所有 BlocProvider,我不想遵循這種不好的做法。
假設當我導航到ScreenA時,我們按如下方式創建Bloc :
case PageNames.screenA:
return PageTransition( // Some class that navigates
duration: const Duration(milliseconds: 400),
child: BlocProvider<ScreenABloc>(
create: (context) => ScreenABloc(),
child: const ScreenAPage(),
),
);
現在在ScreenA內,我將導航到ScreenB ,一切都很好,但是在我的小部件樹底部的ScreenB內,我想再次訪問ScreenABloc ,但我無法分配BlocProvider.value
因為我得到:
ProviderNotFoundException (Error: Could not find the correct Provider<ScreenABloc> above this Welcome Widget
return BlocProvider.value(
value: BlocProvider.of<ScreenABloc>(context),
child: child ...
);
所以我不確定如何獲得已經創建的供應商,或者我是否應該重新創建它或者在這些情況下該怎么做。
您可以在屏幕本身中創建一個創建BlocProvider
的方法,然后您可以使用該方法為您導航和創建提供者。
這是一個例子:
class MyWidget extends StatelessWidget {
const MyWidget({super.key});
static Widget create() {
return MultiBlocProvider(
providers: [
BlocProvider<SignInBloc>(
create: (BuildContext context) => SignInBloc(),
),
],
child: const SignInScreen(),
);
}
@override
Widget build(BuildContext context) {
return Container();
}
}
推送新路線時,您應該使用BlocProvider.value
:
/// declare the bloc
final _screenABloc = ScreenABloc();
然后在ScreenA
和ScreenB
中使用它
case PageNames.screenA:
return PageTransition( // Some class that navigates
duration: const Duration(milliseconds: 400),
child: BlocProvider.value(
value: _screenABloc,
child: const ScreenAPage(),
),
);
case PageNames.screenB:
return PageTransition( // Some class that navigates
duration: const Duration(milliseconds: 400),
child: BlocProvider.value(
value: _screenABloc,
child: const ScreenBPage(),
),
);
在文件開頭使用所有BlocProviders
並不總是被認為是不好的做法。 根據官方文檔
默認情況下,
BlocProvider
將lazily
創建 bloc,這意味着創建將在通過 BlocProvider.of(context) 查找 bloc 時執行。
那么現在,在全球范圍內使用providers
的用例是什么?
當您想訪問應用程序中幾乎所有位置的提供商時。
什么時候使用通過路由的providers
?
當只有一些屏幕需要訪問
bloc
時,您可以使用BlocProvider.value
傳遞值
根據BlocProvider
中flutter_bloc
的官方文檔,按照以下步驟將BlocProvider
傳遞給子屏幕。
BlocA()
BlocProvider(
lazy: false,
create: (BuildContext context) => BlocA(),
child: ChildA(),
);
BlocA
的值傳遞給ScreenA()
確保這是從ChildA()
內部調用的
BlocProvider.value(
value: BlocProvider.of<BlocA>(context),
child: ScreenA(),
);
ChildA
或ScreenA
檢索值如下:// with extensions
context.read<BlocA>();
// without extensions
BlocProvider.of<BlocA>(context);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.