1

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: '[email protected]', 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: [email protected] 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("[email protected]", "37503230") 

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

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

1 Comment

I'm glad it helped you. Welcome to StackOverflow and enjoy coding!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.