Q:

Flutter i got Unhandled Exception that the method validate can not call on null

i try to post http request to reset password, and i use Form widget with TextFormField to do it, but i get an error that the method validate().

i wrapped the TextFormField in a Form with a key, also i use the validator in the TextFormField.

[ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: NoSuchMethodError: The method 'validate' was called on null.

below is the widget code which i use to perform that.

import 'dart:io';

import 'package:Zabatnee/common_app/provider/user_details_provider.dart';
import 'package:Zabatnee/common_app/screens/signup_screen.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class ResetPassword extends StatefulWidget {
  static const routeName = '/resetCode';

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

class _ResetPasswordState extends State<ResetPassword> {
  final GlobalKey<FormState> _formKey = GlobalKey();
String code, _newPassword, _newConfirmPassword;
  var _isLoading = false;

  _showDialog(String title, String message, [bool navigate = false]) {
    showDialog(
      barrierDismissible: false,
      context: context,
      builder: (ctx) => WillPopScope(
        onWillPop: () async => false,
        child: new AlertDialog(
          elevation: 15,
          shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.all(Radius.circular(8))),
          title: Text(
            title,
            style: TextStyle(color: Colors.white),
          ),
          content: Text(
            message,
            style: TextStyle(color: Colors.white),
          ),
          backgroundColor: Theme.of(context).primaryColor,
          actions: <Widget>[
            FlatButton(
              child: Text(
                'OK',
                style: TextStyle(color: Theme.of(context).accentColor),
              ),
              onPressed: () {
                Navigator.of(context).pop();
                setState(
                  () {
                    _isLoading = false;
                  },
                );
                if (navigate) {
                  Navigator.of(context).pushNamed(SignupScreen.routeName);                 
                }
              },
            )
          ],
        ),
      ),
    );
  }

  void _removeFocus (){
   FocusScopeNode currentFocus = FocusScope.of(context);
   if(!currentFocus.hasPrimaryFocus){
     currentFocus.unfocus();
   }

  }
  Future<void> _resetPassword(String userCode, String userNewPassword) async{
    _removeFocus();
    final _isValid = _formKey.currentState.validate();
    if(!_isValid){
      return null;
    }
    _formKey.currentState.save();

    setState(() {
      _isLoading = true;
    });
    try{
      await Provider.of<UserDetailsProvider>(context, listen: false).resetPassword(userCode, userNewPassword);
      _showDialog('Congartulations', 'Account has been created successfully.', true);
    }on HttpException catch (error) {
      _showDialog('Authentication Failed', error.message);
    } on SocketException catch (_) {
      _showDialog('An error occured',
          'please check your internet connection and try again later');
    } catch (error) {
      _showDialog('Authentication Failed',
          'Something went wrong, please try again later');
    }
    setState(() {
      _isLoading = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    GlobalKey<FormState> _formKey = GlobalKey();
    final _newPasswordFocusNode = FocusNode();
    final _confirmPasswordFocusNode = FocusNode(); 
    
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.transparent,
        centerTitle: true,
        title: Text('Reset Password'),
      ),
      backgroundColor: Colors.transparent,
      body: Container(
        margin: EdgeInsets.all(20),
        padding: EdgeInsets.all(16),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            Text(
              'Please enter new password', 
              style: TextStyle(color:Colors.white, fontWeight: FontWeight.bold, fontSize: 20),             
              ),
              SizedBox(
                height: 30,
              ),
            Form(
              key: _formKey,
              child: Column(
                children: <Widget>[
                  TextFormField(
                   decoration: InputDecoration(
                      hintText: 'please enter reset code (check your email)',
                      focusColor: Theme.of(context).primaryColor,
                      fillColor: Colors.white,
                      labelText: 'Reset Code',
                      hintStyle: TextStyle(color:Colors.grey),
                      labelStyle: TextStyle(color:Colors.white),
                      enabledBorder: OutlineInputBorder(
                  borderRadius: BorderRadius.all(Radius.circular(4)),
                  borderSide: BorderSide(width: 1, color: Colors.grey),
                ),
                border: OutlineInputBorder(
                    borderSide:
                        BorderSide(color: Theme.of(context).primaryColor)),
                    ),
                   textInputAction: TextInputAction.next,
                    style: TextStyle(color:Colors.white),
                    onFieldSubmitted: (_){
                      FocusScope.of(context).requestFocus(_newPasswordFocusNode);
                    },
                    validator: (value){
                      if (value.isEmpty) {
                        return 'please enter a valid code';
                      }
                      return null;
                    },
                    onSaved: (value){
                      code = value;
                    },
                      
                  ),
                  SizedBox(
                    height: 15,
                  ),
                   TextFormField(
                     keyboardType: TextInputType.visiblePassword,
                     textInputAction: TextInputAction.next,
                     style: TextStyle(color:Colors.white),
                     onFieldSubmitted: (_){
                       FocusScope.of(context).requestFocus(_confirmPasswordFocusNode);
                     },
                     validator: (value){
                       if(value.length<6){
                         return 'please enter password lager that 6 character';
                       }
                       return null;
                     },
                     onSaved: (value){
                       _newPassword = value;
                     },
                    decoration: InputDecoration(
                      hintText: 'please enter your password',
                      focusColor: Theme.of(context).primaryColor,
                      fillColor: Colors.white,
                      labelText: 'New password',
                      hintStyle: TextStyle(color:Colors.grey),
                      labelStyle: TextStyle(color:Colors.white),
                      enabledBorder: OutlineInputBorder(
                  borderRadius: BorderRadius.all(Radius.circular(4)),
                  borderSide: BorderSide(width: 1, color: Colors.grey),
                ),
                border: OutlineInputBorder(
                    borderSide:
                        BorderSide(color: Theme.of(context).primaryColor)),
                    ),
                  ),
                  SizedBox(
                    height: 15,
                  ),
                   TextFormField(
                     keyboardType: TextInputType.visiblePassword,
                     textInputAction: TextInputAction.done,
                     style: TextStyle(color:Colors.white),
                     onFieldSubmitted: (_){
                       FocusScope.of(context).requestFocus(_confirmPasswordFocusNode);
                     },
                     validator: (value){
                       if(value.length<6){
                         return 'please enter password lager that 6 character';
                       }
                       return null;
                     },
                     onSaved: (value){
                       _newConfirmPassword = value;
                     },
                    decoration: InputDecoration(
                      hintText: 'please retype your new password again',
                      focusColor: Theme.of(context).primaryColor,
                      fillColor: Colors.white,
                      labelText: 'Re-type new password',
                      hintStyle: TextStyle(color:Colors.grey),
                      labelStyle: TextStyle(color:Colors.white),
                      enabledBorder: OutlineInputBorder(
                       borderRadius: BorderRadius.all(Radius.circular(4)),
                       borderSide: BorderSide(width: 1, color: Colors.grey[100]),
                        ),
                      border: OutlineInputBorder(
                        borderSide:
                        BorderSide(color: Theme.of(context).primaryColor)),
                         ),
                  ),
                  SizedBox(
                    height: 30,
                  ),
                  if(_isLoading)
                  CircularProgressIndicator(
                    backgroundColor: Theme.of(context).primaryColor,
                  ),
                  if(!_isLoading)
                  RaisedButton(
                    child: Text('Reset', style: TextStyle(color:Colors.white, fontSize: 20),),
                    onPressed: (){
                      _resetPassword(code, _newPassword);
                    })
                ],
              ),
              )  
          ],
        ),
      ),
    );
  }
}

A:

You declared 2 GlobalKeys under the same name _formKey. One is a field in the State class, the other at the top of the build method.
The key being passed to the form you're using is the one in build, which is overwritten on each build, because a new key is created and passed.
In your _resetPassword method, the classwide GlobalKey is used. This key is not attached to anything, and therefore, _formKey.currentState in that scope is null. This is what causes your exception.
To fix, simply remove GlobalKey<FormState> _formKey = GlobalKey(); from the beginning of your build method. The classwide GlobalKey will now be used instead.

