gpt4 book ai didi

flutter - BlocProvider.of() 使用不包含 Bloc 的上下文调用 - 即使它包含

转载 作者:行者123 更新时间:2023-12-04 11:05:49 60 4
gpt4 key购买 nike

首先,我确实知道 BLoC 应该如何工作,它背后的想法和我知道 BlocProvider() 之间的区别和 BlocProvider.value()构造器。

为简单起见,我的应用程序有 3 个页面,其中包含一个像这样的小部件树:
App() => LoginPage() => HomePage() => UserTokensPage()
我要我的 LoginPage()有权访问 UserBloc因为我需要登录用户等。为此,我将 LoginPage() 包裹起来。 build 者在 App()像这样的小部件:

void main() => runApp(App());

class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My App',
home: BlocProvider<UserBloc>(
create: (context) => UserBloc(UserRepository()),
child: LoginPage(),
),
);
}
}

这显然工作得很好。然后,如果用户登录成功,他将被导航到 HomePage .现在,我需要在我的 HomePage 上访问两个不同的区块。所以我使用 MultiBlocProvider通过现有 UserBloc进一步创建一个全新的名为 DataBloc .我这样做:
  @override
Widget build(BuildContext context) {
return BlocListener<UserBloc, UserState>(
listener: (context, state) {
if (state is UserAuthenticated) {
Navigator.of(context).push(
MaterialPageRoute<HomePage>(
builder: (_) => MultiBlocProvider(
providers: [
BlocProvider.value(
value: BlocProvider.of<UserBloc>(context),
),
BlocProvider<DataBloc>(
create: (_) => DataBloc(DataRepository()),
),
],
child: HomePage(),
),
),
);
}
},
[...]

这也有效。当来自 HomePage 时出现问题用户导航到 UserTokensPage .在 UserTokensPage我需要我现有的 UserBloc我想通过 BlocProvider.value()构造函数。我这样做:
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: false,
title: Text('My App'),
actions: <Widget>[
CustomPopupButton(),
],
),

[...]

class CustomPopupButton extends StatelessWidget {
const CustomPopupButton({
Key key,
}) : super(key: key);

@override
Widget build(BuildContext context) {
return PopupMenuButton<String>(
icon: Icon(Icons.more_horiz),
onSelected: (String choice) {
switch (choice) {
case PopupState.myTokens:
{
Navigator.of(context).push(
MaterialPageRoute<UserTokensPage>(
builder: (_) => BlocProvider.value(
value: BlocProvider.of<UserBloc>(context),
child: UserTokensPage(),
),
),
);
}
break;
case PopupState.signOut:
{
BlocProvider.of<UserBloc>(context).add(SignOut());
Navigator.of(context).pop();
}
}
},
[...]

当我按下按钮导航到 MyTokensPage我收到错误消息:
════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following assertion was thrown building Builder(dirty):
BlocProvider.of() called with a context that does not contain a Bloc of type UserBloc.

No ancestor could be found starting from the context that was passed to BlocProvider.of<UserBloc>().

This can happen if:
1. The context you used comes from a widget above the BlocProvider.
2. You used MultiBlocProvider and didn't explicity provide the BlocProvider types.

Good: BlocProvider<UserBloc>(create: (context) => UserBloc())
Bad: BlocProvider(create: (context) => UserBloc()).

The context used was: CustomPopupButton

我究竟做错了什么?是不是因为我提取了 PopupMenuButton不知何故丢失块的小部件?我不明白我做错了什么。

最佳答案

我修好了它。内App我创建的小部件 LoginPage

home: BlocProvider<UserBloc>(
create: (context) => UserBloc(UserRepository()),
child: LoginPage(),

LoginPage我只是简单地包装 BlocBuilders一个到另一个
Widget build(BuildContext context) {
return BlocListener<UserBloc, UserState>(
listener: (context, state) {
if (state is UserAuthenticated) {
Navigator.of(context).push(
MaterialPageRoute<HomePage>(
builder: (_) => BlocProvider.value(
value: BlocProvider.of<UserBloc>(context),
child: BlocProvider<NewRelicBloc>(
create: (_) => NewRelicBloc(NewRelicRepository()),
child: HomePage(),
),
),
),
);
}
},
[...]
PopupMenuButton将用户导航到 TokenPage
              Navigator.of(context).push(
MaterialPageRoute<UserTokensPage>(
builder: (_) => BlocProvider.value(
value: BlocProvider.of<UserBloc>(context),
child: UserTokensPage(),
),
),
);

这解决了我所有的问题。

关于flutter - BlocProvider.of() 使用不包含 Bloc 的上下文调用 - 即使它包含,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59902356/

60 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com