FCM背景隔离群与主隔离群如何通讯

问题描述 投票:0回答:1

我正在我的应用程序中构建一个聊天部分。当我完成从服务器发送到设备的数据消息的处理时,我意外地遇到了一个严重的问题,即 firebase 打开一个新的隔离来运行后台任务。我使用 GetX 控制器

ChatController
,它有一个
chats
类型的
RxList<Chat>
变量。每个聊天都有一个消息列表。通常,当有人发送消息并且设备位于前台时,我会获取新消息,到处进行一些序列化,然后将其添加到
ChatController
chats
中相应的聊天中。当在后台做同样的事情时,它只是重新初始化一个没有数据的新消息,这会停止添加新消息的过程。

我尝试让聊天控制器永久存在,但没有成功。如何使 firebase 的后台隔离利用现有的聊天控制器?即使用户从顶部拖动来查看通知,我也无法更新

chats
。这真是荒唐至极。

if (Get.isRegistered<ChatController>()) {
  // If the controller is already registered, reuse it
  chatController = Get.find<ChatController>();
  print("Chat Controller Found");
} else {
  // If the controller is not registered, initialize it
  chatController = Get.put(ChatController());
  await chatController
      .getChats(); // Only fetch chats on the first initialization
  print("Chat Controller Created!");
}


chatController.addMessageToChat(
    int.parse(message.data["chat_id"]),
    chatMessage,
);

ChatController.dart:

class ChatController extends GetxController with WidgetsBindingObserver {
  final DioClient _dioClient = DioClient();

  RxInt currentChat = (-1).obs;
  RxList<Chat> chats = <Chat>[].obs;

  RxBool isInBackground = false.obs;
  RxList<ChatMessage> backgroundMessages = <ChatMessage>[].obs;
  RxList<ChatMessage> chatMessages = <ChatMessage>[].obs;

  @override
  void onInit() {
    super.onInit();
    getChats();
    WidgetsBinding.instance.addObserver(this); // Add observer for app lifecycle
  }

  @override
  void onClose() {
    WidgetsBinding.instance
        .removeObserver(this); // Remove observer when controller is destroyed
    super.onClose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) {
      // App comes back to foreground, refresh data
      isInBackground.value = false;

      for (ChatMessage message in backgroundMessages) {
        print("Message added from backgroundMessages");
        addMessageToChat(message.chatId, message);
      }
      backgroundMessages.clear();
    } else if (state == AppLifecycleState.paused) {
      isInBackground.value = true;
    }
    print("isInBackground from life cycle: ${isInBackground.value}");
  }

  void addMessageToChat(int chatId, ChatMessage message) {
    print("isInBackground from add message: ${isInBackground.value}");
    // if (isInBackground.value) {
    //   backgroundMessages.add(message);
    //   print("Message added to backgroundMessages");
    //   return;
    // } else {
    //   print("Message added to chatMessages");
    // }
    // Find the chat
    Chat chat = chats.firstWhere((chat) => chat.id == chatId);

if (chat.id != -1) {
  chat.messages.add(message);
  Map messageMap = message.toMap();

  messageMap['created_at'] = formatMessageDate(
      message.createdAt.toLocal().toIso8601String(),
      Global.activeUser!.timezone ?? "UTC");
  messageMap['sender']['name'] =
      messageMap['sender']['member_id'] == chat.userId
          ? "You"
          : messageMap['sender']['name'];

  if (messageMap['sender']['member_id'] != chat.userId) {
    chat.counter = currentChat.value != chatId ? chat.counter + 1 : 0;
  }

  chat.lastMessageMap = messageMap;

  // Update the list by reordering the chat without rebuilding the entire list
  int currentIndex = chats.indexOf(chat);
  if (currentIndex != 0) {
    chats.removeAt(currentIndex);
    chats.insert(0, chat);

    chats.refresh(); // This will trigger a partial rebuild
  }
}
 }
android flutter firebase-cloud-messaging dart-isolates
1个回答
0
投票

根据我的经验,最简单的方法是使用数据库;

您必须考虑两种情况:

  • 应用程序完全关闭,Firebase 系统会启动您的操作几秒钟,此时它将在数据库中保存信息。

  • 应用程序位于后台,但系统仍然保持其活动状态,在这种情况下,我将使用 WidgetsBindingObserver 将数据库中的信息与您需要的信息同步。

我的建议是使用 Hive,它很简单,对于这样的同步任务我已经使用过它,它对我来说效果很好。

请记住,在后台隔离无法修改 UI 组件。

© www.soinside.com 2019 - 2024. All rights reserved.