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),
),
],
),
);
}
}
どんな助けでも大歓迎です。ありがとう!