2
votes

Comment utiliser les données du fournisseur pendant initState dans l'application Flutter

Je refactore le code de mon application Flutter en ajoutant Provider en tant que gestion d'état.

Comportement souhaité: lorsque l'écran d'accueil s'ouvre, l'application doit vérifier si les e-mails des utilisateurs sont vérifiés, si ce n'est pas le cas, la boîte de dialogue s'affiche.

Problème: Cela fonctionnait bien lorsque je transmettais des données pour EmailVerified via le constructeur, mais si je veux utiliser Provider, je ne peux pas obtenir ces données au cycle de vie initState() .

Pouvez-vous me recommander une approche correcte pour un tel cas d'utilisation?

import 'package:myapp/services/authentication.dart';
import 'package:myapp/screens/settings_screen.dart';
import 'package:flutter/material.dart';
import 'package:myapp/services/authentication.dart';
import 'package:provider/provider.dart';

class HomeScreen extends StatefulWidget {

  @override
  State<StatefulWidget> createState() => new _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  final GlobalKey<FormState> formKey = GlobalKey<FormState>();
  bool _isEmailVerified = false;

  @override
  void initState() {
    super.initState();
    _checkEmailVerification(); // <=== Method which should show Dialog box if email is not verified which is coming from "Auth" Provider
  }

  @override
  Widget build(BuildContext context) {
    final auth = Provider.of<Auth>(context, listen: false); // <==== Service from Provider, which contains data for _isEmailVerified
    auth.isEmailVerified().then((value) => _isEmailVerified = value);

    return new Scaffold(
      appBar: new AppBar(
        title: new Text('My App'),
      ),
      body: Center(
        child: Column(
          children: <Widget>[
            Text(
              'Welcome to my app',
            ),
          ],
        ),
      ),
    );
  }

  void _checkEmailVerification() async {
    _isEmailVerified = auth.isEmailVerified(); // <=== How can I use "auth" from Provider to get isEmailVerified data ????
    if (!_isEmailVerified) {
      _showVerifyEmailDialog();
    }
  }

  void _showVerifyEmailDialog() {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        // return object of type Dialog
        return AlertDialog(
          title: new Text("Verify your account"),
          content: new Text("Please verify account in the link sent to email"),
          actions: <Widget>[
            new FlatButton(
              child: new Text("Resend link"),
              onPressed: () {
                Navigator.of(context).pop();
                _resentVerifyEmail();
              },
            ),
            new FlatButton(
              child: new Text("Dismiss"),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
          ],
        );
      },
    );
  }

  void _resentVerifyEmail() {
    // Logic to send email
  }
}


0 commentaires

3 Réponses :


11
votes

Vous devez utiliser le contexte pour appeler Provider.of() afin que vous puissiez ajouter addPostFrameCallback() qui est appelé après la première construction, vous pouvez utiliser le contexte

@override
void initState() {
    super.initState();

    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      auth = Provider.of<Auth>(context, listen: false);
    });
}


2 commentaires

Merci beaucoup @Sebastian. De plus, si quelqu'un d'autre est confronté à ce problème, je recommande l'article suivant, il explique pourquoi showDialog ne fonctionne pas comme prévu et à quoi sert addPostFrameCallback () - didierboelens.com/faq/week2


@ Sebastian Cela fonctionnait sous Android et non sous iOS. Dans iOS lève une erreur Exception non gérée: 'package: provider / src / provider.dart': Échec de l'assertion: ligne 240 pos 12: 'context! = Null': n'est pas vrai. Merci.



2
votes

Depuis Provider v4.1.0 , vous pouvez également utiliser la méthode read () . Cela réduit le code standard.

@override
void initState() {
  super.initState();

  WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
    auth = context.read<Auth>();
  });
}


0 commentaires

0
votes

Dans la version 3.0.0 + 1, vous pouvez également faire

tu peux le faire avec

var CallNotifier auth;


@override
void initState(){
 super.initState();
 auth = Provider.of<CallNotifier>(context, listen = false);
}


0 commentaires