In Flutter I currently have the following basic app structure (simplified):
class MyProvider extends ChangeNotifier {
String get value => 'Hello!';
}
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider.value(value: MyProvider()),
],
builder: (context, _) => MaterialApp(
home: Scaffold(
body: Center(
child: Text(context.read<MyProvider>().value),
),
),
),
);
}
}
Now, MyProvider
needs an async init
method. I thought I could initialize the provider in the main function and then pass it along to the app and eventually to the MultiProvider, like so:
class MyProvider extends ChangeNotifier {
Future<void> init() async {
// Something async
}
String get value => 'Hello!';
}
Future<void> main() async {
final myProvider = MyProvider();
await myProvider.init();
final app = MyApp(
providers: [
myProvider,
],
);
runApp(app);
}
class MyApp extends StatelessWidget {
const MyApp({super.key, this.providers = const []});
final List<ChangeNotifier> providers;
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
...providers.map((p) => ChangeNotifierProvider.value(value: p)),
],
builder: (context, _) => MaterialApp(
home: Scaffold(
body: Center(
child: Text(context.read<MyProvider>().value),
),
),
),
);
}
}
However, this doesn’t work as it throws a ProviderNotFoundException
.
I’m struggling to see why though. To me, the two versions seem almost identical, as the actual ChangeNotifierProvider
is created in the same place. Only the value is created somewhere else.
Am I doing something obviously wrong?
As a side note, I know I could make my app work by wrapping the MaterialApp
inside a FutureBuilder
and initializing the provider there, but that just looks ugly and suboptimal.
2
Answers
You can wrap MyApp widget into MultiProvider
Update your provider like this:
When you initialize the provider, the
init
function is automatically called.