Home > Back-end >  How to get the return of Futur function call with class Provider.of?
How to get the return of Futur function call with class Provider.of?

Time:11-15

I'm building an app with flutter and I have a question about Provider.of. In my Widget I call this :

Provider.of<Auth>(context, listen: false).signup(emailController.text, passwordController.text);

And I would like to navigate with Navigator according to the return of my signup function. I tried multiple other ways but couldn't make it work.

Naively I tried this:

onPressed: () {
  var result = Provider.of<Auth>(context, listen: false)
      .signup(emailController.text,
          passwordController.text);
  if (result == "failed") {
                              Navigator.of(context).push(MaterialPageRoute(
      builder: (ctx) => SuccessfulScreen()));
  } else {
                              Navigator.of(context).push(MaterialPageRoute(
      builder: (ctx) => UnsuccessfulScreen()));
  }
},

But I got this type for the var result: Future<String>

Here is my tree of my project:

lib/
├── firebase_options.dart
├── images
├── main.dart
├── model
│   └── apis
│       └── auth.dart
└── view
    └── screens
        ├── login_screen.dart
        ├── signup_screen.dart
        ├── successful_screen.dart
        └── welcome_screen.dart

And the auth.dart contains this :

import 'package:flutter/foundation.dart';
import 'package:firebase_auth/firebase_auth.dart';

class Auth with ChangeNotifier {
  Future<String> signup(String email, String password) async {
    try {
      await FirebaseAuth.instance.createUserWithEmailAndPassword(
        email: email,
        password: password,
      );
    } on FirebaseAuthException catch (e) {
      if (e.code == 'weak-password') {
        return e.code;
      } else if (e.code == 'email-already-in-use') {
        return e.code;
      }
    } catch (e) {
      return e.toString();
    }
    return "succes";
  }

  Future<void> login(String email, String password) async {
    try {
      await FirebaseAuth.instance
          .signInWithEmailAndPassword(email: email, password: password);
    } on FirebaseAuthException catch (e) {
      if (e.code == 'user-not-found') {
        print('No user found for that email.');
      } else if (e.code == 'wrong-password') {
        print('Wrong password provided for that user.');
      }
    }
  }
}

I could make this logic directly in my build function (login_screen.dart) but I found that not easy to maintain. So I make it difficult for me but my guess is that I'm missing something, could someone help me on this ?

CodePudding user response:

Add the "async" keyword in the body of function and the "await" keyword before the call of your signup method, like this.

onPressed: () async {
  var result = await Provider.of<Auth>(context, listen: false)
      .signup(emailController.text,
          passwordController.text);
  if (result == "failed") {
                              Navigator.of(context).push(MaterialPageRoute(
      builder: (ctx) => SuccessfulScreen()));
  } else {
                              Navigator.of(context).push(MaterialPageRoute(
      builder: (ctx) => UnsuccessfulScreen()));
  }
},

CodePudding user response:

I often do this using callbacks:

class ClientManager extends ChangeNotifier {

  final FirebaseAuth auth = FirebaseAuth.instance;
 
  Client? client;

  bool _loading = false;

  bool get loading => _loading;

  set loading(bool value) {
    _loading = value;
    notifyListeners();
  }

  Future<void> signUP({
    required Client client,
    required Function(String) onFail,
    required Function() onSuccess,
  }) async {
    loading = true;
    try {
      final UserCredential result = await auth.createUserWithEmailAndPassword(
          email: client.email!, password: client.password!);

      client.id = result.user!.uid;
      this.client = client;

      await client.saveData();
      onSuccess();
      
    } on FirebaseAuthException catch (e) {
      loading = false;
      onFail(e.code);
    }

    loading = false;
  }

}
 Consumer<ClientManager>(
                          builder: (_, clientManager, __) {
                            return ElevatedButton(
                              onPressed:  clientManager.loading
                                  ? null
                                  : () {
                                    clientManager.signUP(
                                    client: client,
                                    onFail: (e) {
                                      ScaffoldMessenger.of(context)
                                          .showSnackBar(
                                        SnackBar(
                                          backgroundColor:
                                          Theme.of(context).errorColor,
                                          content: const Text(
                                              'Register'),
                                        ),
                                      );
                                    },
                                    onSuccess: () {
                                      Navigator.of(context)
                                          .pushReplacementNamed('/');
                                    },
                                  );
                                
                              },
                              child: clientManager.loading
                                  ? const SizedBox(
                                      width: 25,
                                      height: 25,
                                      child: OSCircularIndicator())
                                  : Text(AppLocalizations.of(context)!.login,
                                      style: const TextStyle(
                                          fontSize: 18,
                                          fontWeight: FontWeight.bold)),
                            );
                          }
                        ),
  • Related