首页 > 解决方案 > 必须初始化不可为空的实例字段“verificationId”

问题描述

我是学习颤振的初学者。所以,这段代码给了我不可为空的错误。

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:sf_haven/pages/homePage.dart';

enum LoginVerification{
  DEVICE_VERIFICATION_STATE,
  OTP_VERIFICATION_STATE
}

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

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

class _LoginPageState extends State<LoginPage> {

  LoginVerification cState = LoginVerification.DEVICE_VERIFICATION_STATE;

  final deviceController = TextEditingController();
  final otpController = TextEditingController();
  FirebaseAuth _auth = FirebaseAuth.instance;

  String verificationId; //I'm getting that error here
  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)=> HomePage()));
      }
    } on FirebaseAuthException catch (e) {
      setState(() {
        showLoading = false;
      });
      _scaffoldkey.cState.showSnackBar(SnackBar(content: Text(e.message))); //here at cState and e.message
    }
  }

  getDeviceFormWidget(context){
    return Column(
      children:[
        Spacer(),

        TextField(
          controller: deviceController,
          decoration: InputDecoration(
            hintText: "Phone Number",
          ),
        ),
        SizedBox(
          height: 16,
        ),
        FlatButton(
          onPressed: () async{
            
            setState(() {
              showLoading = true;
            });

            await _auth.verifyPhoneNumber(
              phoneNumber: deviceController.text,
              verificationCompleted: (phoneAuthCredential) async{
                setState(() {
                  showLoading = false;
                });
                //signInWithPhoneAuthCredential(phoneAuthCredential;)
              },
              verificationFailed: (verificationFailed) async{
                setState(() {
                  showLoading = false;
                });
                _scaffoldkey.cState.showSnackBar(SnackBar(content: Text(verificationFailed.message))); //here at cState and  verificationFailed.message
              },
              codeSent: (verificationId, resendingToken) async{
                setState((){
                  showLoading = false;
                  cState = LoginVerification.OTP_VERIFICATION_STATE;
                  this.verificationId = verificationId;
                });
              },
              codeAutoRetrievalTimeout: (verificationId) async{

              },
            );
          },
          child: Text("Send"),
          color: Colors.blue,
          textColor: Colors.white,
        ),

        Spacer(),
      ],
    );
  }

  getOTPformWidget(context){
    return Column(
      children: [
        Spacer(),
        TextField(
          controller: otpController,
          decoration: InputDecoration(
            hintText: "Enter OTP",
          ),
        ),
        SizedBox(
          height: 16,
        ),
        FlatButton(
          onPressed: () async{
            PhoneAuthCredential phoneAuthCredential = PhoneAuthProvider.credential(verificationId: verificationId, smsCode: otpController.text);
            signInWithPhoneAuthCredential(phoneAuthCredential);
          },
          child: Text("Verify"),
          color: Colors.blue,
          textColor: Colors.white,
        ),
        Spacer(),
      ],
    );
  }

  final GlobalKey<ScaffoldState> _scaffoldkey = GlobalKey<ScaffoldState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldkey,
      body: Container(
        child:  showLoading ? Center(child: CircularProgressIndicator(),) : cState == LoginVerification.DEVICE_VERIFICATION_STATE
                ? getDeviceFormWidget(context)
                : getOTPformWidget(context),
        padding: const EdgeInsets.all(13),
      )
    );
  }
}

我收到不可为空的实例字段“verificationId”必须verificationId在和处初始化错误cState。非常感谢....请忽略这部分,因为我试图通过大量的文字来解决....为什么我不能发布我的答案....

标签: flutterdartfirebase-authentication

解决方案


只是改变:

String verificationId;

至:

String? verificationId;

“Null Safety”强制您说出变量何时为空,从而避免一些错误。所以,当一个变量可以为空并且没有被初始化时,你应该使用'?为了说明这一点,此外,在使用可以为空的变量内部的资源时,有必要确保值的存在,这样您就不会访问空值。例如,

ClientModel? date;

if (date!.name == "Username")....

使用“!”时 您确保在那个特定时刻这个变量不会为空。


推荐阅读