![](/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.