Null Safety Issue in flutter

Viewed 226
    if (_formKey.currentState.validate()) {
        setState(() {
          buttonChanged = false;
        });
      
    }

according to my logic, the above statement would let me sign in with a login and password validation, but i keep getting an error

The method 'validate' can't be unconditionally invoked because the receiver can be 'null'. Try making the call conditional (using '?.') or adding a null check to the target ('!').

when i do if (_formKey.currentState!.validate()) error goes away but my validation does not work, login happens even when it shouldnt.

Kindly help me with this issue, i am a beginner, learning flutter app developement via youtube.

this is my whole code


import 'package:flutter/material.dart';
import 'routes.dart';

class LoginPage extends StatefulWidget {
  const LoginPage({Key? key}) : super(key: key);

  @override
  State<LoginPage> createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  bool buttonChanged = false;
  String name = "";
  final _formKey = GlobalKey<FormState>();

  moveToHome(BuildContext context) async {
    if (_formKey.currentState.validate()) {
      setState(() {
        buttonChanged = false;
      });
    }

    await Future.delayed(const Duration(seconds: 1));
    await Navigator.pushNamed(context, route.home);
    setState(() {
      buttonChanged = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Material(
      color: Colors.grey[500],
      child: Form(
        key: _formKey,
        child: Column(
          children: [
            const CircleAvatar(backgroundImage: AssetImage('images/login.jpg')),
            const SizedBox(height: 15.0),
            Text('Welcome $name',
                style: const TextStyle(
                    fontSize: 24.0, fontWeight: FontWeight.bold)),
            const SizedBox(height: 15.0),
            Padding(
                padding:
                    const EdgeInsets.symmetric(horizontal: 15, vertical: 32),
                child: Column(
                  children: [
                    TextFormField(
                        decoration: const InputDecoration(
                            hintText: 'Enter the username',
                            labelText: 'UserName:'),
                        onChanged: (value) {
                          name = value;
                          setState(() {});
                        },
                        validator: (value) {
                          if (value != null && value.isEmpty) {
                            return 'Please enter the username';
                          }

                          return null;
                        }),
                    TextFormField(
                        obscureText: true,
                        decoration: const InputDecoration(
                            hintText: 'Enter the password',
                            labelText: 'Password:'),
                        validator: (value) {
                          if (value != null && value.isEmpty) {
                            return 'Please enter the password';
                          } else if (value != null && value.length < 6) {
                            return 'Password must be atleast 6 characters';
                          } else {
                            return null;
                          }
                        }),
                    const SizedBox(height: 15.0),
                    Material(
                        borderRadius:
                            BorderRadius.circular(buttonChanged ? 50.0 : 10.0),
                        color: Colors.blue,
                        child: InkWell(
                          splashColor: Colors.red,
                          onTap: () => moveToHome(context),
                          child: AnimatedContainer(
                            duration: const Duration(seconds: 1),
                            width: buttonChanged ? 50 : 130,
                            height: 50,
                            alignment: Alignment.center,
                            child: buttonChanged
                                ? const Icon(Icons.done)
                                : const Text(
                                    'Login',
                                    style: TextStyle(
                                        color: Colors.white,
                                        fontWeight: FontWeight.bold,
                                        fontSize: 16),
                                  ),
                          ),
                        ))
                  ],
                ))
          ],
        ),
      ),
    );
  }
}





1 Answers

Your validation logic must be:

If the user’s input isn’t valid, the validator function returns a String containing an error message. If there are no errors, the validator must return null.

But you're using incorrect code in your validator property. The following code:

validator: (value) {
  if (value != null && value.isEmpty) {
    return 'Please enter the username';
  }

  return null;
}),

will always return null if you haven't insert the text to TextFormField. So,

_formKey.currentState!.validate() will always return true if both of your TextFormFields are without text.

To solve the problem, change the code like the following:

validator: (value) {
  if (value == null || value.isEmpty) {
    return 'Please enter the username';
  }

  return null;
}),
Related