我正在使用 Bloc/Cubit (flutter_bloc) 和 Auto_Router 包
我在 /counter 路由上有计数器,在 /user_profile 路由上有 FloatingActionButtons 来增加计数器。
如何从不同的页面/路由增加计数器?我应该能够在页面之间来回切换并从任一页面增加/减少,但我收到以下错误消息:
发生异常。ProviderNotFoundException(错误:在此 UserProfilePage 小部件上方找不到正确的提供程序
发生这种情况是因为您使用了BuildContext
不包括您选择的提供者的 。有几种常见的场景:
您在您的中添加了一个新的提供程序
main.dart
并执行了热重载。要修复,请执行热重启。您尝试读取的提供程序位于不同的路径中。
提供者是“范围的”。因此,如果您在路由中插入提供程序,那么其他路由将无法访问该提供程序。
您使用的
BuildContext
是您尝试读取的提供程序的祖先。确保 UserProfilePage 在您的 MultiProvider/Provider 下。这通常发生在您创建提供程序并尝试立即读取它时。
例如,而不是:
Widget build(BuildContext context) { return Provider<Example>( create: (_) => Example(), // Will throw a ProviderNotFoundError, because `context` is associated // to the widget that is the parent of `Provider<Example>` child: Text(context.watch<Example>()), ), }
考虑
builder
像这样使用:Widget build(BuildContext context) { return Provider<Example>( create: (_) => Example(), // we use `builder` to obtain a new `BuildContext` that has access to the provider builder: (context) { // No longer throws return Text(context.watch<Example>()), } ), }
如果这些解决方案都不起作用,请考虑在 StackOverflow 上寻求帮助: https ://stackoverflow.com/questions/tagged/flutter )
这是我的代码:
home_page.dart
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return AutoTabsScaffold(
appBarBuilder: (_, tabsRouter) => AppBar(
backgroundColor: Colors.indigo,
title: const Text('FlutterBottomNav'),
centerTitle: true,
leading: const AutoBackButton(),
),
backgroundColor: Colors.teal,
routes: const [
CounterRouter(),
PostsRouter(),
UsersRouter(),
SettingsRouter(),
],
bottomNavigationBuilder: (_, tabsRouter) {
return SalomonBottomBar(
margin: const EdgeInsets.symmetric(
horizontal: 20,
vertical: 40,
),
currentIndex: tabsRouter.activeIndex,
onTap: tabsRouter.setActiveIndex,
items: [
SalomonBottomBarItem(
selectedColor: Colors.amberAccent,
icon: const Icon(Icons.plus_one, size: 30),
title: const Text('Counter'),
),
SalomonBottomBarItem(
selectedColor: Colors.amberAccent,
icon: const Icon(Icons.post_add, size: 30),
title: const Text('Posts'),
),
SalomonBottomBarItem(
selectedColor: Colors.blue[200],
icon: const Icon(
Icons.person,
size: 30,
),
title: const Text('Users'),
),
SalomonBottomBarItem(
selectedColor: Colors.pinkAccent[100],
icon: const Icon(
Icons.settings,
size: 30,
),
title: const Text('Settings'),
),
],
);
},
);
}
}
counter_cubit.dart
class CounterCubit extends Cubit<int> {
CounterCubit() : super(0);
void increment() => emit(state + 1);
void decrement() => emit(state - 1);
}
counter_page.dart
class CounterPage extends StatelessWidget {
const CounterPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => CounterCubit(),
child: const CounterView(),
);
}
}
class CounterView extends StatelessWidget {
const CounterView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final l10n = context.l10n;
return Scaffold(
appBar: AppBar(title: Text(l10n.counterAppBarTitle)),
body: const Center(child: CounterText()),
floatingActionButton: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
FloatingActionButton(
key: const Key('counterView_star_floatingActionButton'),
onPressed: () {
print('star');
},
child: const Icon(Icons.star),
),
const SizedBox(height: 8),
FloatingActionButton(
key: const Key('counterView_boat_floatingActionButton'),
onPressed: () {
print('boat');
},
child: const Icon(Icons.sailing),
),
FloatingActionButton(
key: const Key('counterView_increment_floatingActionButton'),
onPressed: () => context.read<CounterCubit>().increment(),
child: const Icon(Icons.add),
),
const SizedBox(height: 8),
FloatingActionButton(
key: const Key('counterView_decrement_floatingActionButton'),
onPressed: () => context.read<CounterCubit>().decrement(),
child: const Icon(Icons.remove),
),
],
),
);
}
}
class CounterText extends StatelessWidget {
const CounterText({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final count = context.select((CounterCubit cubit) => cubit.state);
return Text('$count', style: theme.textTheme.headline1);
}
}
user_profile_page.dart
class UserProfilePage extends StatelessWidget {
final int userId;
const UserProfilePage({
Key? key,
@PathParam() required this.userId,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final user = User.users[userId - 1];
return Scaffold(
backgroundColor: user.color,
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
UserAvatar(
avatarColor: Colors.white,
username: 'user${user.id}',
)
],
),
),
floatingActionButton: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
FloatingActionButton(
key: const Key('counterView_star_floatingActionButton'),
onPressed: () {
print('star');
},
child: const Icon(Icons.star),
),
const SizedBox(height: 8),
FloatingActionButton(
key: const Key('counterView_boat_floatingActionButton'),
onPressed: () {
print('boat');
},
child: const Icon(Icons.sailing),
),
FloatingActionButton(
key: const Key('counterView_increment_floatingActionButton'),
onPressed: () => context.read<CounterCubit>().increment(),
child: const Icon(Icons.add),
),
const SizedBox(height: 8),
FloatingActionButton(
key: const Key('counterView_decrement_floatingActionButton'),
onPressed: () => context.read<CounterCubit>().decrement(),
child: const Icon(Icons.remove),
),
],
),
);
}
}
非常感谢任何帮助。谢谢!