0

I am a novice to flutter. Mine is a phone verification app.

I am stuck with the following error :Null check operator used on a null value. The complete error message is here: The following _CastError was thrown building Builder:

Null check operator used on a null value

The relevant error-causing widget was: MaterialApp file:///E:/AndroidStudioProjects/phone_verification/lib/main.dart:18:12 When the exception was thrown, this was the stack: #0 _InitializerWidgetState.initState (package:phone_verification/main.dart:48:30) #1 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4711:57) #2 ComponentElement.mount (package:flutter/src/widgets/framework.dart:4548:5) ... Normal element mounting (166 frames) #168 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3611:14)

As I could not solve the issue by the solutions provided here I am posting the question again. Please suggest possible changes in my code. Running on Channel stable. Flutter version is 2.2.3. Thanks

main.dart

    import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_core/firebase_core.dart' show Firebase;
import 'package:flutter/material.dart';
import 'package:phone_verification/screens/homeScreen.dart';
import 'package:phone_verification/screens/loginScreen.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Phone Verification',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      debugShowCheckedModeBanner: false,
      home: InitializerWidget(),
    );
  }
}

class InitializerWidget extends StatefulWidget {

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

class _InitializerWidgetState extends State<InitializerWidget> {

  late FirebaseAuth _auth;

  late User _user;

  bool isLoading = true;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _auth = FirebaseAuth.instance;
    _user = _auth.currentUser!;
    bool isLoading = false;
  }
  @override
  Widget build(BuildContext context) {
    return isLoading ? Scaffold(
      body: Center(
        child: CircularProgressIndicator(),
      ),
    ) : _user == null ? LoginScreen() : HomeScreen();
  }
}

loginScreen.dart

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:phone_verification/screens/homeScreen.dart';

enum MobileVerificationState {
  SHOW_MOBILE_FORM_STATE,
  SHOW_OTP_FORM_STATE,
}

class LoginScreen extends StatefulWidget {
  @override
  _LoginScreenState createState() => _LoginScreenState();
}

class _LoginScreenState extends State<LoginScreen> {
  MobileVerificationState currentState = MobileVerificationState.SHOW_MOBILE_FORM_STATE;

  final phoneController = TextEditingController();
  final otpController = TextEditingController();

  FirebaseAuth _auth = FirebaseAuth.instance;

 late String verificationId;

 bool showLoading = false;

  void signInWithPhoneAuthCredential(PhoneAuthCredential phoneAuthCredential) async {

    setState(() {
      showLoading = true;
    });
    try {
      final authCredential = await _auth.signInWithCredential(phoneAuthCredential);

      setState(() {
        showLoading = false;
      });

      if(authCredential.user != null)
        {
          Navigator.push(context,MaterialPageRoute(builder: (context)=> HomeScreen()));
        }

    }on FirebaseAuthException catch (e) {

      setState(() {
        showLoading = false;
      });

      _scaffoldKey.currentState!.showSnackBar(SnackBar(content: Text(e.message.toString())));
    }
  }

  getMobileFormWidget(context) {
    return Column(
      children: [
        Spacer(),
        TextField(
          controller: phoneController,
          decoration: InputDecoration(hintText: "Phone Number"),
        ),
        SizedBox(
          height: 16.0,
        ),
        SizedBox(
          width: 10.0,
        ),
        TextButton(
          onPressed: ()async {

            setState(() {
              showLoading = true;
            });

            await _auth.verifyPhoneNumber(
              phoneNumber: phoneController.text,
              verificationCompleted: (phoneAuthCredential) async {
                setState(() {
                  showLoading = false;
                });
                //signInWithPhoneAuthCredential(phoneAuthCredential);
              },
              verificationFailed: (verificationFailed) async {
                setState(() {
                  showLoading = false;
                });
                _scaffoldKey.currentState!.showSnackBar(SnackBar(content: Text(verificationFailed.message.toString())));
              },
              codeSent: (verificationId, resendingToken) async {
                setState(() {
                  showLoading = false;
                  currentState = MobileVerificationState.SHOW_OTP_FORM_STATE;
                  this.verificationId = verificationId;
                });
              },
              codeAutoRetrievalTimeout: (verificationId) async {

              },
            );
          },
          child: Text(
            "SEND",
          ),
          style: TextButton.styleFrom(
            primary: Colors.white,
            backgroundColor: Colors.deepPurple,
          ),
        ),
        Spacer(),
      ],
    );
  }

  getOtpFormWidget(context) {
    return Column(
      children: [
        Spacer(),
        TextField(
          controller: otpController,
          decoration: InputDecoration(hintText: "Enter OTP"),
        ),
        SizedBox(
          height: 16.0,
        ),
        SizedBox(
          width: 10.0,
        ),
        TextButton(
          onPressed: () async {
            PhoneAuthCredential phoneAuthCredential =
            PhoneAuthProvider.credential(verificationId: verificationId, smsCode: otpController.text);

            signInWithPhoneAuthCredential(phoneAuthCredential);

          },
          child: Text(
            "VERIFY",
          ),
          style: TextButton.styleFrom(
            primary: Colors.white,
            backgroundColor: Colors.deepPurple,
          ),
        ),
        Spacer(),
      ],
    );
  }

  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,
      body: Container(
          child: showLoading ? Center(child: CircularProgressIndicator(),) : currentState == MobileVerificationState.SHOW_MOBILE_FORM_STATE
              ? getMobileFormWidget(context)
              : getOtpFormWidget(context),
        padding: const EdgeInsets.all(16),

      ));
  }
}

homeScreen.dart

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:phone_verification/screens/loginScreen.dart';

class HomeScreen extends StatefulWidget {

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

class _HomeScreenState extends State<HomeScreen> {

  final _auth = FirebaseAuth.instance;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text("Home Screen"),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          await _auth.signOut();
          Navigator.pushReplacement(context,MaterialPageRoute(builder: (context) => LoginScreen()));
        },
        child: Icon(Icons.logout),
      ),
    );
  }
}
J.Koriya
  • 167
  • 2
  • 11

2 Answers2

1

You are saying that user cant be null _user = _auth.currentUser!; but you are checking if user is null here : _user == null ? LoginScreen() : HomeScreen();

esentis
  • 4,190
  • 2
  • 12
  • 28
1

This is the line. _user = _auth.currentUser!; I understand your logic, but you can't do that. ! operator says this isn't a null variable. Instead of that, use directly:

_user = _auth.currentUser

And then change _user's type to User? instead of User

Hazar Belge
  • 1,009
  • 4
  • 20
  • Thanks Hazar! The error is solved but the app does not load. The app is installted on the device and the loading symbol appears but doesn't go further, i.e, the login screen does not load. Any suggestions? Here is what appears on my console: Debug service listening on ws://127.0.0.1:58796/vIST4OIYE4U=/ws Syncing files to device Redmi 6 Pro... The app stops here. – J.Koriya Aug 31 '21 at 04:16
  • Hi, I figured out the answer for my second question. I was just initializing the bool isLoading=false. It is working now. Thanks. – J.Koriya Aug 31 '21 at 06:46