web-dev-qa-db-fra.com

Flutter get context dans la méthode initState

Je ne sais pas si la initState est la bonne fonction pour cela . Ce que j'essaie de faire est de vérifier quand la page est rendue pour effectuer certaines vérifications et en se basant sur elles, ouvrant une AlertDialog pour effectuer certains réglages si nécessaire. .

J'ai une page qui a un état . C'est une fonction initState qui ressemble à ceci:

@override
void initState() {
    super.initState();
    if (!_checkConfiguration()) {
        _showConfiguration(context);
    }
}

Le _showConfiguration comme ceci:

void _showConfiguration(BuildContext context) {
    AlertDialog dialog = new AlertDialog(
        content: new Column(
            children: <Widget>[
                new Text('@todo')
            ],
        ),
        actions: <Widget>[
            new FlatButton(onPressed: (){
                Navigator.pop(context);
            }, child: new Text('OK')),
        ],
    );

    showDialog(context: context, child: dialog);
}

S'il existe un meilleur moyen de procéder à cette vérification et, si nécessaire, d'appeler le modal, veuillez me diriger dans la bonne direction. Je cherchais une fonction onState ou onRender ou un rappel que je pouvais affecter à la fonction build à appeler, mais n'a pas pu en trouver un.


Edit: Il semble ici qu'ils avaient un problème similaire: Flutter Redirect vers une page sur initState

8
wawa

Le contexte est disponible pendant initState, mais vous devez envelopper le code qui pousse la boîte de dialogue dans un futur pour qu'il ne se termine que sur l'image suivante.

Voici un exemple complet:

import 'Dart:async';

import 'package:flutter/material.Dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  bool _checkConfiguration() => true;

  void initState() {
    super.initState();
    if (_checkConfiguration()) {
      new Future.delayed(Duration.zero,() {
        showDialog(context: context, builder: (context) => new AlertDialog(
          content: new Column(
            children: <Widget>[
              new Text('@todo')
            ],
          ),
          actions: <Widget>[
            new FlatButton(onPressed: (){
              Navigator.pop(context);
            }, child: new Text('OK')),
          ],
        ));
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new Center(
        child: new Column(
            mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new Text(
              'You have pushed the button this many times:',
            ),
            new Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
    );
  }
}

Il convient de noter le new Future.delayed(Duration....). En effet, vous ne pouvez pas faire des choses comme pousser des pages sur un navigateur pendant la phase de construction entre le moment où la fonction de génération est appelée et celle où elle se termine. Un avenir différé fait que le code à l'avenir s'exécute dès que le code en cours d'exécution est terminé.

Edit: avec plus de contexte de l'OP, cette partie suivante n'est plus pertinente.

Une autre option puisque cela se fait dans une page - où que vous poussiez la page depuis (où vous devez avoir un contexte ou vous ne pouvez pas appuyer sur Push), vous pouvez faire la vérification et ouvrir la boîte de dialogue à partir de là (ou au moins exposer une méthode quelque part qui fait la poussée et puis aussi la vérification).

Modifier à nouveau: avec plus de contexte de l'OP, je peux donner une solution légèrement meilleure. En fonction de l'application, vous souhaiterez peut-être prendre une décision en fonction de la page à afficher, qu'il s'agisse de la première ouverture de l'application ou non, définissez home sur quelque chose de différent. Les dialogues ne sont pas nécessairement le meilleur élément d'interface utilisateur sur le mobile; il est probablement préférable d'afficher une page complète avec les paramètres à ajouter, ainsi qu'un bouton Suivant.

7
rmtmckenzie

Vous devez utiliser le paquet AfterLayout, vérifiez simplement son exemple et il fournit une belle solution à ce problème

https://pub.dartlang.org/packages/after_layout

1
Muhammad Adil

Envelopper avec Future

  @override
  void initState() {
    super.initState();
    _store = Store();
    new Future.delayed(Duration.zero,() {
      _store.fetchContent(context);
    });
  }
1
Pablo Cegarra