Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use data from Provider during initState in Flutter application

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

like image 650
Maxim Vershinin Avatar asked Feb 21 '20 17:02

Maxim Vershinin


People also ask

How do I get the context in initState in flutter?

If you instead make an asynchronous call which delegates your call until after the widget has been initialized, you can then use context as you intend. A simple way to do that is to use a future. With more context from the OP provided in comments, I can give a slightly better solution to their specific problem.

How does provider in Flutter work?

Example Using Provider dart , all we have to do is call Provider. of<String>(context) , the of() method here will obtain the nearest Provider up its widget tree and returns its value. Also in the code above, we are reading the value, in this case there is no way to update unless we update the value in the code.

What is initState method in flutter?

initState() is a method of class State and it is considered as an important lifecycle method in Flutter. initState() is called only Once and we use it for one time initializations. Example : To initialize data that depends on the specific BuildContext . To initialize data that needs to executed before build() .


1 Answers

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

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

    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      auth = Provider.of<Auth>(context, listen: false);
    });
}
like image 104
Sebastian Avatar answered Oct 14 '22 14:10

Sebastian