wake-up-neo.net

Flatter-Get-Kontext in der initState-Methode

Ich bin nicht sicher, ob initState die richtige Funktion dafür ist . Was ich versuche zu erreichen, ist zu prüfen, wann die Seite gerendert wird, um einige Überprüfungen durchzuführen, und basierend darauf, dass ein AlertDialog geöffnet wird, um bei Bedarf einige Einstellungen vorzunehmen .

Ich habe eine Seite, die einen Zustand hat . Die Funktion initState sieht folgendermaßen aus:

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

Der _showConfiguration gefällt mir so:

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);
}

Wenn es eine bessere Möglichkeit gibt, diese Überprüfungen durchzuführen und wenn nötig das modal aufzurufen, weisen Sie mich bitte in die richtige Richtung. Ich habe nach einer onState- oder onRender-Funktion gesucht oder nach einem Callback, den ich der build-Funktion zuweisen könnte, der aber beim Rendern aufgerufen wird konnte keinen finden.


Edit: Es sieht so aus, als hätten sie ein ähnliches Problem: Flutter Weiterleitung zu einer Seite in initState

8
wawa

Der Kontext ist während initState verfügbar, aber Sie müssen den Code einbetten, der den Dialog in eine Zukunft schiebt, sodass er nur im nächsten Frame abgeschlossen wird.

Hier ist ein konkretes Beispiel:

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,
            ),
          ],
        ),
      ),
    );
  }
}

Bemerkenswert ist die new Future.delayed(Duration....). Dies liegt daran, dass Sie in der Erstellungsphase zwischen dem Aufrufen der Erstellungsfunktion und dem Beenden der Erstellungsfunktion keine Elemente wie Push-Seiten auf einen Navigator ausführen können. Bei einer verzögerten Zukunft wird der Code in der Zukunft ausgeführt, sobald der aktuell ausgeführte Code beendet ist.

Edit: Mit mehr Kontext aus dem OP ist dieser nächste Teil nicht mehr relevant.

Eine weitere Option, da dies auf einer Seite geschieht - wo auch immer Sie die Seite per Push übertragen (wo Sie einen Kontext haben müssen oder nicht können), können Sie das Dialogfeld prüfen und öffnen (oder zumindest eine Methode verfügbar machen irgendwo macht das den Push und dann auch den Check).

Nochmal editieren: Mit mehr Kontext aus dem OP kann ich eine etwas bessere Lösung geben. Abhängig von der App möchten Sie möglicherweise eine Entscheidung basierend auf der anzuzeigenden Seite treffen, je nachdem, ob die App zum ersten Mal geöffnet wird, d. H. home auf etwas anderes gesetzt wird. Dialoge sind nicht unbedingt das beste UI-Element auf mobilen Geräten. Es ist wahrscheinlich besser, eine vollständige Seite mit den Einstellungen, die sie hinzufügen müssen, und eine nächste Schaltfläche anzuzeigen.

7
rmtmckenzie

Sie müssen das AfterLayout-Paket verwenden, checken Sie es einfach aus und es bietet eine hervorragende Lösung für dieses Problem

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

1
Muhammad Adil

Umwickeln mit Future

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

Einfache Verwendung Timer.run()

@override
void initState() {
  super.initState();
  Timer.run(() {
    // you have a valid context here
  });
}
0
CopsOnRoad