dart Flutter:StreamBuilder在新数据到来时不会自动更新ListView

bq3bfh9z  于 2023-05-26  发布在  Flutter
关注(0)|答案(1)|浏览(198)

在我的聊天应用程序中,当后端有更新/新数据时,我试图自动更新列表。我使用StreamBuilder来做到这一点,但当后端数据更改时,它不会更新ListView。我在后台服务器端使用的是一个带有mysql作为数据库的spring Boot 服务器。我发现的大多数聊天应用程序示例都是基于firebase作为服务器的,这并没有帮助我解决这个问题。我在这里做错了什么,请帮助纠正这个问题,因为我是一个flutter初学者。

class ChatScreen extends ConsumerStatefulWidget {
final dynamic data;
final dynamic category;
const ChatScreen({
    Key? key, required this.data, required this.category,
}) : super(key: key);

@override
ConsumerState<ChatScreen> createState() => _ChatScreenState();
}

class _ChatScreenState extends ConsumerState<ChatScreen> with SingleTickerProviderStateMixin {

dynamic dataItem;
List<dynamic>? chatList = [];

@override
void initState() {
  super.initState();
}

@override
Widget build(BuildContext context) {
  return Container(
  child: WillPopScope(
    child: showChat(),
   ),);
}

showChat() {
  return StreamBuilder<dynamic>(
  stream: ref.watch(chatControllerProvider).getChatsList(widget.data['id'],widget.category['id']),
  builder: (context, snapshot) {
    if (!snapshot.hasData) {
      return const Loader();
    } else if(snapshot.data!.isEmpty) {
      return NoChat();
    } else {
      dataItem = snapshot.data!['chatRoom'];
      chatList = snapshot.data!['chatList'];
      return showChatView();
    }
  },);
}

showChatView() {
  int dataLength = chatList!.length;
  return Column(
    children: [
      Expanded(child: ListView(
        reverse: true,
        padding: EdgeInsets.all(20),
        children: List.generate(chatList!.length, (index) {
          return MessageBox(
            data: chatList![dataLength - 1 - index],
          );
        },),
      ),),
    ],
  );
}

}

import 'package:flutter_riverpod/flutter_riverpod.dart';

import '../../chat_repository.dart';

final chatControllerProvider = Provider<ChatController>(
(ref) {
    final chatApi = ref.watch(chatRepositoryProvider);
    return ChatController(chatApi: chatApi, ref: ref);
},
);

class ChatController {
ChatController({
    required ChatApi chatApi,
    required ProviderRef ref,
})  : _chatApi = chatApi,
        _ref = ref;

final ChatApi _chatApi;
final ProviderRef _ref;

Stream<dynamic> getChatsList(int roomId,int categoryId) async* {
    var result = await _chatApi.getRoomChatList(roomId,categoryId);
    yield result;
}
}

import 'package:flutter_riverpod/flutter_riverpod.dart';
import '...../chat_api.dart';

final chatRepositoryProvider = Provider<ChatApi>((ref) {
return ChatApi();
});

class ChatApi{
late Dio dioRest;

ChatApi() {
    dioRest = Dio(
    BaseOptions(
        headers: {
        HttpHeaders.contentTypeHeader: ContentType.json.value,
        },
    ),
    );
}

Future getRoomChatList(int roomId,int categoryId) async {
    try {
    token = getToken();
    var result = await dioRest.post(token.baseUrl!+'..../getRoomChatList',options: Options(.....),
        queryParameters: {'roomId' : roomId,'categoryId' : categoryId},
    );
    if (result.statusCode == 200) {
        return jsonDecode(result.data);
    }
    throw DioError(requestOptions: result.requestOptions);
    } on DioError catch (error) {
    if (error.response!.statusCode! >= 400) {
        throw TokenException(message: "Token invalid or expired");
    }
    throw BusinessException(BusinessError.fromJson(error.response?.data), statusCode: error.response?.statusCode);
    } catch (error) {
    throw Error();
    }
}

}
gr8qqesn

gr8qqesn1#

从您的代码片段来看,您似乎只在ChatController中的getChatsList()函数中获取了一次聊天列表。然而,在实时聊天应用程序中,当新消息到达时,您需要侦听来自后端的更新。
ChatController中的方法getChatsList()返回一个Stream,但是您得到的是一个用async*yield Package 的API调用的结果,当有新数据时,它不会自动更新。
举一个实际的例子,我假设您正在使用Firebase,保持聊天实时更新的一种常见方法是使用onValue事件侦听器。当使用onValue时,Firebase会在每次数据更改时自动调用您的回调函数,从而允许您的聊天实时更新。
下面是一个如何使用它的例子:

Stream<dynamic> getChatsList(int roomId,int categoryId) {
  return _chatApi.getRoomChatList(roomId, categoryId).asStream();
}

Future getRoomChatList(int roomId,int categoryId) async {
  try {
    token = getToken();
    DatabaseReference chatRef = FirebaseDatabase.instance
        .reference()
        .child('rooms')
        .child(roomId.toString())
        .child(categoryId.toString());

    chatRef.onValue.listen((event) {
      var data = event.snapshot.value;
      // process data as needed
      return data;
    });

  } catch (error) {
    throw Error();
  }
}

在上面的示例中,将侦听器添加到特定聊天室的Firebase数据库引用中。对数据库中该位置的任何更改都将触发onValue事件并实时更新您的数据。
这只是一个一般的例子。您必须根据特定的Firebase数据库结构调整数据库引用。
现在,由于我怀疑你使用的是Firebase或类似的实时数据库,而是REST API,因此实时更新更加复杂,可能涉及其他技术,如WebSocket,服务器发送事件(SSE)或推送通知。你需要检查你的后端是否支持这些。

相关问题