Firebase Auth, Error: NoSuchMethodError: The method 'login' was called on null

Viewed 88

I'm new to flutter and I try to make login Authentication with firebase Auth but return with "Error: NoSuchMethodError: The method 'login' was called on null."

loginPage:

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_custom_clippers/flutter_custom_clippers.dart';
import 'package:topride/src/pages/login/login_controller.dart';
import 'package:topride/src/pages/register/register_controller.dart';
import 'package:topride/src/pages/register/register_page.dart';

import 'package:topride/src/widgets/button_app.dart';

class LoginPage extends StatefulWidget {



  @override
  _LoginPageState createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  LoginController _con = new LoginController();

  @override
  void setState(VoidCallback fn) {
    // TODO: implement setState
    super.setState(fn);
    SchedulerBinding.instance.addPostFrameCallback((timeStamp) {
      _con.init(context);
    });
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),

      body: SingleChildScrollView(
        child: Column(
          children: [
            _bannerApp(),
            _textDescription(),
            _textLogin(),
            SizedBox(height: MediaQuery.of(context).size.height*0.17,),
            _textFieldEmail(),
            _textFieldPassword(),
            _buttonLogin(),
            _textDontHaveAccount(),
        ],
        ),
      ),
    );
  }
  Widget _bannerApp(){
    return ClipPath(
      clipper: WaveClipperTwo(),
      child:  Container(
        color: Colors.black54,

        height: MediaQuery.of(context).size.height*0.22,

        child: Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            Image.asset(
              'assets/img/logo_app.png',
              width: 150,
              height: 100,
            ),
            Text(
              'Facile et Rapide',
              style: TextStyle(
                  fontFamily: 'Racing',
                  fontSize: 22,
                  fontWeight: FontWeight.w700,
                  color: Colors.white
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _textDescription(){
    return Container(
      alignment: Alignment.centerLeft,
      margin: EdgeInsets.symmetric(horizontal: 30,vertical: 10),
      child: Text('Continuez avec votre',
        style: TextStyle(
          color: Colors.black54,
          fontSize: 20,
          fontFamily: 'Nimbus'
        ),
      ),
    );
  }

  Widget _textLogin(){
    return Container(
      alignment: Alignment.centerLeft,
      margin: EdgeInsets.symmetric(horizontal: 30),
      child: Text('Login',
        style: TextStyle(
          color: Colors.black,
              fontWeight: FontWeight.bold,
          fontSize: 28,

        ),
      ),
    );
  }


  Widget _textFieldEmail(){
    return Container(
      margin: EdgeInsets.symmetric(horizontal: 30,vertical: 10),
      child: TextField(
        controller: _con.emailController,
        decoration: InputDecoration(
          hintText: 'example@gmail.com',
          labelText: 'Address E-mail',
            suffixIcon: Icon(
              Icons.email_outlined,
              color: Colors.black54,
            ),
        ),
      ),
    );
  }

  Widget _textFieldPassword(){
    return Container(
      margin: EdgeInsets.symmetric(horizontal: 30,vertical: 15),
      child: TextField(
        obscureText: true,
        controller: _con.passwordController,
        decoration: InputDecoration(

          labelText: 'Mot de Passe',
          suffixIcon: Icon(
            Icons.lock_clock_outlined,
            color: Colors.black54,
          ),
        ),
      ),
    );
  }

  Widget _buttonLogin (){

    return Container(
      margin: EdgeInsets.symmetric(horizontal: 30,vertical: 25),
        child: ButtonApp(onPressed:_con.login,text:'Connexion',));
  }




  Widget _textDontHaveAccount(){
    return

       TextButton(onPressed:() => navigateToRegister(context),
         child: Container(
          margin: EdgeInsets.only(bottom: 50),
          child: Text(
            'Ne pas avoir de compte ? ', style: TextStyle(
            color: Colors.black54,
            fontSize: 15,
          ),
          ),
      ),
       );

  }

  navigateToRegister(BuildContext context) {
    Navigator.of(context)
        .push(MaterialPageRoute<Null>(builder: (BuildContext context) {
      return RegisterPage();
    }));
  }
}

loginController :

import 'package:flutter/material.dart';
import 'package:topride/src/providers/auth_provider.dart';

class LoginController{

  BuildContext context;

  TextEditingController emailController = new TextEditingController();
  TextEditingController passwordController = new TextEditingController();

  AuthProvider _authProvider;

  Future init(BuildContext context){
    this.context=context;
    _authProvider=new AuthProvider();
  }



  void login()async{
    String email = emailController.text.trim();
    String password =passwordController.text.trim();
    print('email: $email');
    print('password: $password');

    try{
     bool isLogin= await _authProvider.login(email, password);
     if(isLogin){
       print('the user is logged in ');
     }
     else{
       print('the user is not login');
     }
    }catch(error){
      print('Error: $error');
    }

  }
}

authProvider:

import 'package:firebase_auth/firebase_auth.dart';

class AuthProvider {

  FirebaseAuth _firebaseAuth;

  AuthProvider(){
    _firebaseAuth = FirebaseAuth.instance;
  }

  Future<bool> login(String email ,String password)async{
    String errorMessage;

    try{
   await _firebaseAuth.signInWithEmailAndPassword(email: email, password: password);
    }catch(error){
      print(error);
      //invalid email
      //incorrect password
      //no internet connection
      errorMessage=error.Code;
    }
    if(errorMessage!=null){
      return Future.error(errorMessage);
    }
    return true;
  }
}

Run:

I/flutter (10810): email: ahmed.alqasim@gmail.com
I/flutter (10810): password: 37503230
I/flutter (10810): Error: NoSuchMethodError: The method 'login' was called on null.
I/flutter (10810): Receiver: null
I/flutter (10810): Tried calling: login("ahmed.alqasim@gmail.com", "37503230")

I also add account on firebase wish the same email and password for test , please help this is driving me crazy

1 Answers

In your LoginPage widget, is there a specific reason you overrode setState method? I assume you wanted to use initState instead. Here is the suggested snippet for you:

  LoginController _con = new LoginController();

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) async {
      await _con.init(context);
      setState((){}); //this line is necessary for the widget to know the controller has been updated
    });
  }

And then if you want to make sure the login method is only called on an initialized controller, you can add a field into the controller, something like bool _isInitialized = false and update it in your init method to true.

Also, if you don't need to call any async methods, instead of having an async init function in your LoginController, you could just have a default constructor :

LoginController(this.context) {
  _authProvider = new AuthProvider();
}

By the way, the keyword new is optional in Flutter so you can just remove it anywhere you use it.

Related