首页 > 解决方案 > Firebase 身份验证,错误:NoSuchMethodError:在 null 上调用了方法“登录”

问题描述

我是 Flutter 的新手,我尝试使用 firebase Auth 进行登录身份验证,但返回“错误:NoSuchMethodError:方法‘登录’被调用为空。”

登录页面:

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();
    }));
  }
}

登录控制器:

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');
    }

  }
}

身份验证提供者:

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

跑:

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")

我还在firebase上添加帐户希望相同的电子邮件和密码进行测试,请帮助这让我发疯

标签: firebaseflutter

解决方案


在您的小部件中,是否有您覆盖方法LoginPage的特定原因?setState我假设您想initState改用。以下是为您推荐的片段:

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

然后,如果您想确保仅在初始化的控制器上调用登录方法,您可以在控制器中添加一个字段,例如bool _isInitialized = false并将其在您的init方法中更新为true.

此外,如果您不需要调用任何async方法,而不是在您的 中使用 asyncinit函数LoginController,您可以只使用默认构造函数:

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

顺便说一句,newFlutter 中的关键字是可选的,因此您可以在使用它的任何地方将其删除。


推荐阅读