Flutter – How to use data from Provider during initState in Flutter application

flutter, flutter-layout, flutter-provider, flutter-state, state-management

I am refactoring my Flutter application code by adding Provider as a state management.

Desired behavior: When Home screen opens, app should check if users email verified, if it's not then should show dialog popup.

Problem: It worked fine when I was passing data for EmailVerified through the constructor, but if I want to use Provider, I can't get this data at initState() lifecycle.

Can you please recommend me correct approach for such use case?

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

Best Solution

You need to use the context to call Provider.of() so you can add addPostFrameCallback() which is called after the first build, there you can use the context

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