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

Stream报错NoSuchMethodError:在null上调用[]方法,求解决方案

Stream 抛出 NoSuchMethodError: The method '[]' was called on null 问题分析与修复

问题描述

使用Stream时遇到错误:NoSuchMethodError: The method '[]' was called on null,添加打印语句后输出的data内容正常,但Stream仍返回该错误。

打印的data结果:

{ userId1: 59jTMEbvqFd8C8UhInksauAVNk63, userId2: 2ssfDEPhPhcIwInUWdlm0ReH5RZ2, latestMessageTime: Timestamp(seconds=1667140814, nanoseconds=334000000), lastMessageSenderId: 59jTMEbvqFd8C8UhInksauAVNk63, created_at: 2022-10-26 19:44:13.793275, latestMessage: TEST 3, roomId: Qv30s8kATJbFJIWRdBEo }

相关代码:

roomsStream 方法

Stream<RoomsListModel> roomsStream() async* { 
  try { 
    var rooms = await FirebaseFirestore.instance.collection("rooms")
        .where("users", arrayContains: userId)
        .orderBy("latestMessageTime", descending: true)
        .snapshots(); 
    print("rooms: $rooms"); 
    await for (var room in rooms) { 
      for (var doc in room.docs) { 
        var data = doc.data() as Map<String, dynamic>; 
        print("data: $data"); 
        var otherUser = await getOtherUser(data["users"][0] == userId ? data["users"][1] : data["users"][0]); 
        print("otherUser: $otherUser"); 
        yield RoomsListModel(
          roomId: doc.id, 
          userId: otherUser["user id"], 
          avatar: otherUser["photoUrl"], 
          name: otherUser["name"], 
          lastMessage: data["latestMessage"], 
          lastMessageTime: data["latestMessageTime"]
        ); 
      } 
    } 
  } catch (e) { 
    print("Error: $e"); 
  } 
}

getOtherUser 方法

Future getOtherUser(String id) async { 
  var user = await FirebaseFirestore.instance.collection("users")
      .doc(id)
      .get()
      .then((value) => value.data()) as Map<String, dynamic>; 
  return user; 
}

错误原因

  • 字段不匹配:打印的data中仅包含userId1、userId2字段,不存在代码中访问的users数组,直接调用data["users"][0]等同于在null上调用[]方法,触发错误。
  • 用户文档空值未处理:getOtherUser中强制将value.data()转为Map<String, dynamic>,若指定ID的用户文档不存在,value.data()返回null,强制类型转换会抛出异常;即便转换成功,后续访问otherUser["user id"]等字段时,若otherUser为null也会触发该错误。
  • 异常捕获不完整:getOtherUser内部的异常未被捕获,一旦执行出错会直接中断Stream的执行。

修复方案

1. 修正字段访问逻辑

因为实际数据中存储的是userId1和userId2而非users数组,调整获取另一用户ID的逻辑:

// 替换原获取otherUser的代码行
String otherUserId = data["userId1"] == userId ? data["userId2"] : data["userId1"];
var otherUser = await getOtherUser(otherUserId);

2. 完善getOtherUser的空值处理

避免用户文档不存在时返回null或抛出异常,同时调整返回类型确保类型安全:

Future<Map<String, dynamic>?> getOtherUser(String id) async { 
  var docSnapshot = await FirebaseFirestore.instance.collection("users").doc(id).get();
  if (!docSnapshot.exists) {
    print("用户文档不存在,ID: $id");
    return null; // 也可返回预设的默认用户信息
  }
  return docSnapshot.data() as Map<String, dynamic>?;
}

3. 在Stream中添加空值校验

创建RoomsListModel前先检查otherUser是否为null,避免后续字段访问报错:

if (otherUser != null) {
  yield RoomsListModel(
    roomId: doc.id, 
    userId: otherUser["user id"], 
    avatar: otherUser["photoUrl"], 
    name: otherUser["name"], 
    lastMessage: data["latestMessage"], 
    lastMessageTime: data["latestMessageTime"]
  );
} else {
  print("无法获取用户信息,跳过该房间: ${doc.id}");
}

4. 扩大异常捕获范围

将单个房间文档的处理逻辑也纳入try-catch,避免单个房间处理失败导致整个Stream终止:

await for (var room in rooms) { 
  for (var doc in room.docs) { 
    try {
      var data = doc.data() as Map<String, dynamic>; 
      print("data: $data"); 
      String otherUserId = data["userId1"] == userId ? data["userId2"] : data["userId1"];
      var otherUser = await getOtherUser(otherUserId); 
      print("otherUser: $otherUser"); 
      if (otherUser != null) {
        yield RoomsListModel(
          roomId: doc.id, 
          userId: otherUser["user id"], 
          avatar: otherUser["photoUrl"], 
          name: otherUser["name"], 
          lastMessage: data["latestMessage"], 
          lastMessageTime: data["latestMessageTime"]
        );
      }
    } catch (e) {
      print("处理房间文档失败: ${doc.id}, 错误: $e");
    }
  } 
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 10:50:42