无法获取StreamBuilder数据,报错_ControllerStream不是Iterable子类型
问题原因
- 第一处错误在
getChatData的实现:你当前yield的是getChat(id).asStream(),也就是每次向流中推送的是另一个Stream对象,而不是接口返回的消息列表数据,所以snapshot.data拿到的是流对象而非可遍历的列表,触发类型不匹配报错 - 第二处错误在
getChat的实现:async和then混用导致你没有正确把消息列表作为Future的返回值返回,接口请求到的列表没有被正确传递出去,所以会出现snapshot.data为空的情况
修复代码
1. 修正getChat函数,正确返回消息列表
把then写法改为更清晰的await写法,显式返回最终的消息列表,同时过滤接口返回末尾多余逗号生成的空消息:
Future<List> getChat(orderId) async { SharedPreferences prefs = await SharedPreferences.getInstance(); var _token = prefs.getString('token'); print('The Latest Order Token is $_token'); final Map<String, dynamic> body = { "id": "$orderId", }; final List _messageData = []; var url = Uri.parse('$_server/api/driver/get/convo/?access_token=$_token'); http.Response response = await http.post(url, body: body, headers: { "Content-Type": 'application/x-www-form-urlencoded' }); print(response.body); switch (response.statusCode) { case 200: final Map<String, dynamic> responseData = json.decode(response.body); print("The ${response.body}"); var x = responseData['message_data'].split(","); print(x); for (int i = 0; i < x.length; i++) { // 过滤空字符串,避免接口返回末尾逗号生成的空消息 if(x[i].trim().isNotEmpty) { _messageData.add(x[i]); print(x[i]); } } print(x); break; default: final Map<String, dynamic> responseData = json.decode(response.body); print(responseData); break; } return _messageData; }
2. 修正getChatData函数,推送正确的列表数据
不要把Future转成Stream推送,直接await拿到列表后推送列表本身:
Stream<List> getChatData(Duration refreshTime, id) async* { while (true) { await Future.delayed(refreshTime); yield await getChat(id); } }
3. 可选优化StreamBuilder的状态处理
补充加载、错误状态的展示,同时拆分消息字段区分发送者和消息内容:
StreamBuilder( stream: _chatStream, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } if (snapshot.hasError) { return Center(child: Text('加载失败:${snapshot.error}')); } if (snapshot.hasData) { final messages = snapshot.data as List; List<MessageBubble> messageWidgets = []; for (var message in messages) { // 拆分消息内容区分发送者、消息文本 final splitMsg = message.split(' - '); final senderAndContent = splitMsg[1].split(': '); final msgSender = senderAndContent[0]; final msgText = senderAndContent[1]; final currentUser = "loggedInUser.displayName"; final msgBubble = MessageBubble( msgText: msgText, msgSender: msgSender, user: currentUser == msgSender ); messageWidgets.add(msgBubble); } return Expanded( child: ListView( reverse: true, padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 10), children: messageWidgets, ) ); } return const Center(child: Text('暂无聊天消息')); }, ),
内容的提问来源于stack exchange,提问作者Doing Things Occasionally
相关产品推荐
相关产品推荐

