You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决QR扫码功能中FutureBuilder内的空检查运算符异常?

问题

我正在开发一个QR扫码功能,当未识别到QR码时,通过else if语句显示等待状态:

else if (result == null) {
  return Column(
   children: [ const Text("Welcome!"), Text("Fee:${load["Fee"]}"), ],
  );
} 

但添加FirebaseFirestore的FutureBuilder后,语句late Message data = Message.fromJson(jsonDecode((result!.code!)));会抛出「Null check operator used on a null value」异常,且异常指向该变量语句。希望解决该异常,同时保留else if实现的等待状态显示,完整代码如下:

Barcode? result;
FutureBuilder<DocumentSnapshot>(
  future: FirebaseFirestore.instance
      .collection('Drivers')
      .doc(FirebaseAuth.instance.currentUser?.email)
      .get(),
  builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
    if (snapshot.hasError) { return Text("Something went wrong"); }
    if (snapshot.hasData && !snapshot.data!.exists) { return Text("Document does not exist"); }
    if (snapshot.connectionState == ConnectionState.done) {
      Map<String, dynamic> load = snapshot.data!.data() as Map<String, dynamic>;

          late Message data = Message.fromJson(jsonDecode((result!.code!))); //Null check Operator Runtime Error unless no Builder there.
         int total = data.price * data.passenger;
      return Column(
        children: [
          Row(children: [Text(load["name"]),],),
          Container(
            height: 100,
            child: Row(
              mainAxisAlignment:
                  MainAxisAlignment.spaceEvenly,
              children: [
                Container(child: LayoutBuilder(builder: (context, constraints) {
                  if ((result != null) && (load["Fee"] == data.price)) {
                    return FutureBuilder<DocumentSnapshot>(
                      future: FirebaseFirestore.instance.collection('Users').doc(data.email).get(),
                      builder:(context, snapshot) {
                        if ((snapshot.hasError)||(snapshot.hasData && !snapshot.data!.exists)) { return const Text("Something went wrong, Try again"); }
                        if (snapshot.connectionState == ConnectionState.done) {
                          Map<String, dynamic> moneycheck = snapshot.data!.data() as Map<String, dynamic>;

                          if (moneycheck['Balance'] >= total){
                            return Column(
                              children: [
                                Text("Payment Made! \n ${DateTime.now().toString()}"),
                                Text("Price: RM${data.price} per Person"),
                                Text("Total: RM${data.totalprice}"),
                                Text("Persons: ${data.passenger}"),
                              ],
                            );
                          }
                          else if (moneycheck['Balance'] < total){ return 
                          Column( children: [ Text("Insufficient Balance"),
                                Text("Balance: RM ${moneycheck['Balance']}"),Text("Price: RM${data.price} per Person"),
                                 Text("Total: RM${data.totalprice}"),Text("Persons: ${data.passenger}"),
                              ],
                            );
                           }
                        }
                        return const Text("Loading...");
                      },
                    );
                  } 
                  else if (result == null) {
                    return Column(
                      children: [ const Text("Welcome!"), Text("Fee:${load["Fee"]}"), ],
                    );
                  } 
                  else if ((result != null) && (load["Fee"] != data.price)) 
                  {
                    return Column(
                      children: [ const Text("Invalid QR Code!"), Text("${data.price}"), Text("${data.totalprice}"),],
                    );
                  } 
                  else {
                    return const Column(
                      children: [
                        Text("Unknown Error Occured"),
                      ],
                    );
                  }
                })
                    )
              ],
            ),
          ),
        ],
      );
    }
    return const Text("Loading");
  },
)
解决方案

异常原因是Firebase的FutureBuilder完成后,无论result(扫码结果)是否为null,都会执行result!.code!的强制非空操作,直接触发空指针异常。解决思路是把data的初始化逻辑限制在result非空的分支内,避免空值访问:

  1. 移除全局的late Message data声明,将其移到result != null的判断分支内部,确保只有扫码成功后才初始化data。
  2. 提前处理result == null的情况,在LayoutBuilder的builder中优先判断result是否为空,提前返回等待状态,避免后续代码执行空值操作。
  3. 增加result.code的空值校验,防止扫码结果的code字段为空。

修改后的完整代码:

Barcode? result;
FutureBuilder<DocumentSnapshot>(
  future: FirebaseFirestore.instance
      .collection('Drivers')
      .doc(FirebaseAuth.instance.currentUser?.email)
      .get(),
  builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
    if (snapshot.hasError) { return Text("Something went wrong"); }
    if (snapshot.hasData && !snapshot.data!.exists) { return Text("Document does not exist"); }
    if (snapshot.connectionState == ConnectionState.done) {
      Map<String, dynamic> load = snapshot.data!.data() as Map<String, dynamic>;

      return Column(
        children: [
          Row(children: [Text(load["name"]),],),
          Container(
            height: 100,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                Container(child: LayoutBuilder(builder: (context, constraints) {
                  // 优先处理未扫码状态
                  if (result == null) {
                    return Column(
                      children: [ const Text("Welcome!"), Text("Fee:${load["Fee"]}"), ],
                    );
                  }

                  // 处理扫码结果为空的情况
                  if (result?.code == null) {
                    return const Text("Invalid QR Code: Empty content");
                  }

                  // 安全初始化data
                  Message data = Message.fromJson(jsonDecode(result!.code!));
                  int total = data.price * data.passenger;

                  // 校验费用匹配
                  if (load["Fee"] == data.price) {
                    return FutureBuilder<DocumentSnapshot>(
                      future: FirebaseFirestore.instance.collection('Users').doc(data.email).get(),
                      builder:(context, snapshot) {
                        if ((snapshot.hasError)||(snapshot.hasData && !snapshot.data!.exists)) { 
                          return const Text("Something went wrong, Try again"); 
                        }
                        if (snapshot.connectionState == ConnectionState.done) {
                          Map<String, dynamic> moneycheck = snapshot.data!.data() as Map<String, dynamic>;
                          if (moneycheck['Balance'] >= total){
                            return Column(
                              children: [
                                Text("Payment Made! \n ${DateTime.now().toString()}"),
                                Text("Price: RM${data.price} per Person"),
                                Text("Total: RM${data.totalprice}"),
                                Text("Persons: ${data.passenger}"),
                              ],
                            );
                          } else {
                            return Column( 
                              children: [ 
                                Text("Insufficient Balance"),
                                Text("Balance: RM ${moneycheck['Balance']}"),
                                Text("Price: RM${data.price} per Person"),
                                Text("Total: RM${data.totalprice}"),
                                Text("Persons: ${data.passenger}"),
                              ],
                            );
                          }
                        }
                        return const Text("Loading...");
                      },
                    );
                  } else {
                    return Column(
                      children: [ 
                        const Text("Invalid QR Code!"), 
                        Text("${data.price}"), 
                        Text("${data.totalprice}"),
                      ],
                    );
                  }
                }))
              ],
            ),
          ),
        ],
      );
    }
    return const Text("Loading");
  },
)

内容的提问来源于stack exchange,提问作者Q40

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 23:37:02