Flutter用StreamBuilder读Firestore报错method 'data' was called on null
问题原因
你的报错核心是代码执行顺序错误,和initState无关:你在StreamBuilder的builder回调中,先执行了snapshot.data.data()提取数据,再做错误判断、加载状态判断。
StreamBuilder首次触发构建时,Firestore的数据流还没返回结果,此时snapshot.data是null,直接调用data()方法就会触发空指针异常。等后续数据流返回结果后,StreamBuilder会重新构建,此时snapshot.data有值,页面就会正常加载,这就是你看到报错闪一下后页面正常的原因。
修复方案
调整代码执行顺序,先完成加载、错误、非空判断后,再提取文档数据,参考修复后的代码:
_buildBody() { return StreamBuilder<DocumentSnapshot>( // 指定泛型避免类型转换问题 stream: userstream.doc(widget.uid).snapshots(), builder: (context, snapshot){ // 优先判断错误 if(snapshot.hasError){ return const Text('ERROR'); } // 判断加载中状态 if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } // 兜底判断数据是否存在 if (!snapshot.hasData || snapshot.data == null) { return const Text('未查询到对应用户数据'); } // 确认数据非空后再提取内容 Map<String, dynamic> user_data = snapshot.data!.data() as Map<String, dynamic>; return Padding( padding: const EdgeInsets.all(20.0), child: ListView.separated( padding: const EdgeInsets.only(left: 20, right: 20), itemCount: 13, separatorBuilder: (BuildContext context, int index) => const Divider(), itemBuilder: (BuildContext context, int index){ return Center( child: Container( child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Text(datas[index]), // 加兜底避免字段为空时报错 Text(user_data[datas[index]] is int ? user_data[datas[index]].toString() : user_data[datas[index]] ?? '') ], ), ), ); } ) ); }, ); }
内容的提问来源于stack exchange,提问作者flyer
相关产品推荐
相关产品推荐

