Search code examples
firebaseflutterfirebase-authenticationreset-password

Flutter method 'resetPassword' was called on null


I was trying to create a button that allow users to reset their password. However, when I used the method, it was called on null.

I don't know where I did wrong. I checked everything, and it should work since I already implemented that method in my abstract class called BaseAuth.

Can somebody help me please?

This is how I used ResetPasswordPage

@override
Widget build(BuildContext context) {
_isIos = Theme.of(context).platform == TargetPlatform.iOS;
return new Scaffold(
    appBar: new AppBar(
      title: new Text("Organizer"),
      backgroundColor: Colors.blueAccent,
    ),
    body: Stack(
      children: <Widget>[
        _showBody(),
        _showCircularProgress(),
      ],
    ));
     }
Widget _showBody(){
return new Container(
    padding: EdgeInsets.all(10.0),
    child: new Form(
      key: _formKey,
      child: new ListView(
        shrinkWrap: true,
        children: <Widget>[
          _showEmailInput(),
          _showPasswordInput(),
          _showPrimaryButton(),
          _showSecondaryButton(),
          _resetPassword(),
        ],
      ),
    ));
     }
Widget _resetPassword() {
return new Padding(
  padding: EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 0.0),
child : FlatButton(
  child: new Text('Forget password?',
      style:
      new TextStyle(fontSize: 18.0, fontWeight: FontWeight.w300)),
  onPressed: (){
    Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => ResetPasswordPage()),
    );
  }
)
);
}

This is ResetPasswordPage Class

class ResetPasswordPage extends StatefulWidget {
ResetPasswordPage({Key key, this.auth});
final BaseAuth auth;
@override
_ResetPasswordPageState createState() => _ResetPasswordPageState();
}
class _ResetPasswordPageState extends State<ResetPasswordPage> {
String _email = '';
TextEditingController _emailController;
@override
void initState() {
super.initState();
final _emailController = TextEditingController(text: _email);
}

@override
void dispose() {
// Clean up the controller when the widget is disposed.
_emailController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
    appBar: new AppBar(
      title: new Text('Reset Password Page'),
      backgroundColor: Colors.red,
    ),
    body: Container(
      padding: EdgeInsets.all(10.0),
      child: ListView(
        children: <Widget>[
          new Padding(
            padding: const EdgeInsets.fromLTRB(0.0, 100.0, 0.0, 0.0),
            child: new TextField(
              maxLines: 1,
              keyboardType: TextInputType.emailAddress,
              decoration: new InputDecoration(
                  hintText: 'Email',
                  icon: new Icon(
                    Icons.mail,
                    color: Colors.grey,
                  )),
              onChanged: (value) {
                _email = value;
              },
              controller: _emailController,
            ),
          ),
          new Padding(
              padding: const EdgeInsets.fromLTRB(30.0, 20.0, 30.0, 0.0),
              child: RaisedButton(
                child: new Text('Sumbit',
                    style: new TextStyle(
                        fontSize: 18.0, fontWeight: FontWeight.w300)),
                onPressed: () async{
                  try{
                    await widget.auth.resetPassword('guanwenyan301@gmail.com');
                  }catch(e){
                    print(e);
                  }
                },
              ))
        ],
      ),
    ));
    }
     }

This is my BaseAuth Class:

abstract class BaseAuth {

Future<String> signIn(String email, String password);
Future<String> signUp(String email, String password);
Future<FirebaseUser> getCurrentUser();
Future<void> signOut();
Future<void> resetPassword(String email);}

class Auth implements BaseAuth {
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
Future<String> signIn(String email, String password) async {
FirebaseUser user = await _firebaseAuth.signInWithEmailAndPassword(
    email: email, password: password);
if (user.isEmailVerified) {
  return user.uid;
}else{
  Fluttertoast.showToast(msg: 'Please verify your email');
}
}

Future<String> signUp(String email, String password) async {
FirebaseUser user = await _firebaseAuth.createUserWithEmailAndPassword(
    email: email, password: password);
await user.sendEmailVerification();
return user.uid;
}

Future<FirebaseUser> getCurrentUser() async {
FirebaseUser user = await _firebaseAuth.currentUser();
return user;
}

Future<void> signOut() async {
return _firebaseAuth.signOut();
}


Future<void> resetPassword(String email) async {
return _firebaseAuth.sendPasswordResetEmail(email: email);

}}

This is the error that I got:

flutter: NoSuchMethodError: The method 'resetPassword' was called on 
null.
Receiver: null
Tried calling: resetPassword("guanwenyan301@gmail.com")

Solution

  • The issue is here

    ResetPasswordPage({Key key, this.auth});
    final BaseAuth auth;
    

    As you pass the auth from the main widget. But in your code it's missing

    Navigator.push(
          context,
          MaterialPageRoute(builder: (context) => ResetPasswordPage()),
        );
    

    So you need to create the instance of ** Auth** and then pass it to the ResetPasswordPage() in the route.

    ///Initialize the auth object like this

    auth = Auth();
    

    /// and pass it in the onPressed like this

    onPressed: (){
        Navigator.push(
          context,
          MaterialPageRoute(builder: (context) => ResetPasswordPage(auth : auth)), // first auth is the key in ResetPasswordPage and second auth is value 
        );
      }