Le contexte de la variable membre est accessible pendant initState
mais ne peut pas être utilisé pour tout. Ceci provient du flutter pour initState
documentation :
Vous ne pouvez pas utiliser [BuildContext.inheritFromWidgetOfExactType]
de cette méthode. Cependant, [didChangeDependencies]
sera appelé immédiatement après cette méthode, et [BuildContext.inheritFromWidgetOfExactType]
peut y être utilisé.
Vous pourriez déplacer votre logique d'initialisation vers didChangeDependencies
mais ce n'est peut-être pas exactement ce que vous voulez. didChangeDependencies
peut être appelé plusieurs fois dans le cycle de vie du widget.
Si, au contraire, vous effectuez un appel asynchrone qui délègue votre appel jusqu'à ce que le widget ait été initialisé, vous pouvez alors utiliser le contexte comme vous le souhaitez.
Un moyen simple de le faire est d'utiliser un futur.
Future.delayed(Duration.zero,() {
... showDialog(context, ....)
}
Une autre méthode, peut-être plus "correcte", consiste à utiliser le planificateur de Flutter pour ajouter un rappel post-frame :
SchedulerBinding.instance.addPostFrameCallback((_) {
... showDialog(context, ....)
});
Et enfin, voici une petite astuce que j'aime faire pour utiliser des appels asynchrones dans la fonction initState :
() async {
await Future.delayed(Duration.zero);
... showDialog(context, ...)
}();
Voici un exemple complet utilisant le simple Future.delayed :
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
bool _checkConfiguration() => true;
void initState() {
super.initState();
if (_checkConfiguration()) {
Future.delayed(Duration.zero,() {
showDialog(context: context, builder: (context) => AlertDialog(
content: Column(
children: <Widget>[
Text('@todo')
],
),
actions: <Widget>[
FlatButton(onPressed: (){
Navigator.pop(context);
}, child: Text('OK')),
],
));
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
);
}
}
Avec plus de contexte du PO fourni dans les commentaires, je peux donner une solution légèrement meilleure à leur problème spécifique. En fonction de l'application, vous pouvez décider de la page à afficher selon qu'il s'agit de la première ouverture de l'application. home
à quelque chose de différent. De plus, les boîtes de dialogue ne sont pas nécessairement le meilleur élément d'interface utilisateur sur mobile ; il peut être préférable d'afficher une page complète avec les paramètres qu'ils doivent ajouter et un bouton suivant.