Browse SDKs · Flutter
SDKsFlutter

Event overview

Configure OpenIM Flutter SDK listeners centrally and dispatch events by business domain.

Copy

The OpenIM Flutter SDK uses listeners to deliver connection, synchronization, user, relationship, conversation, conversation-group, group, message, and call changes. Each manager retains only one corresponding listener, and a later configuration replaces the Dart instance stored previously. Compose every callback when initializing the application state layer, and configure each listener type exactly once. Do not configure listeners in a widget's build() method or separately on each feature screen.

Configure listeners centrally

The following example shows an application-level composition entry point. The complete merge logic for each handle* function belongs on the ownership page linked in the table below.

Future<void> registerOpenIMListeners() async {
  await OpenIM.iMManager.userManager.setUserListener(
    OnUserListener(
      onSelfInfoUpdated: handleSelfInfoUpdated,
      onUserStatusChanged: handleUserStatusChanged,
    ),
  );

  await OpenIM.iMManager.friendshipManager.setFriendshipListener(
    OnFriendshipListener(
      onBlackAdded: handleBlackAdded,
      onBlackDeleted: handleBlackDeleted,
      onFriendAdded: handleFriendChanged,
      onFriendDeleted: handleFriendDeleted,
      onFriendInfoChanged: handleFriendChanged,
      onFriendApplicationAdded: handleFriendApplicationChanged,
      onFriendApplicationAccepted: handleFriendApplicationChanged,
      onFriendApplicationRejected: handleFriendApplicationChanged,
      onFriendApplicationDeleted: handleFriendApplicationDeleted,
    ),
  );

  await OpenIM.iMManager.conversationManager.setConversationListener(
    OnConversationListener(
      onNewConversation: handleNewConversations,
      onConversationChanged: handleConversationsChanged,
      onTotalUnreadMessageCountChanged: handleTotalUnreadChanged,
      onInputStatusChanged: handleInputStatusChanged,
      onSyncServerStart: handleSyncStart,
      onSyncServerProgress: handleSyncProgress,
      onSyncServerFinish: handleSyncFinish,
      onSyncServerFailed: handleSyncFailed,
    ),
  );

  await OpenIM.iMManager.groupManager.setGroupListener(
    OnGroupListener(
      onJoinedGroupAdded: handleJoinedGroupAdded,
      onJoinedGroupDeleted: handleJoinedGroupDeleted,
      onGroupInfoChanged: handleGroupInfoChanged,
      onGroupDismissed: handleGroupDismissed,
      onGroupMemberAdded: handleGroupMemberAdded,
      onGroupMemberDeleted: handleGroupMemberDeleted,
      onGroupMemberInfoChanged: handleGroupMemberInfoChanged,
      onGroupApplicationAdded: handleGroupApplicationChanged,
      onGroupApplicationAccepted: handleGroupApplicationChanged,
      onGroupApplicationRejected: handleGroupApplicationChanged,
      onGroupApplicationDeleted: handleGroupApplicationDeleted,
    ),
  );

  await OpenIM.iMManager.messageManager.setAdvancedMsgListener(
    OnAdvancedMsgListener(
      onRecvNewMessage: handleNewMessage,
      onRecvOfflineNewMessage: handleOfflineMessage,
      onRecvOnlineOnlyMessage: handleOnlineOnlyMessage,
      onMsgDeleted: handleMessageDeleted,
      onNewRecvMessageRevoked: handleMessageRevoked,
      onRecvC2CReadReceipt: handleC2CReadReceipts,
      onMessageModified: handleMessageModified,
      onChangedPinnedMsg: handlePinnedMessagesChanged,
    ),
  );

  await OpenIM.iMManager.messageManager.setCustomBusinessListener(
    OnCustomBusinessListener(
      onRecvCustomBusinessMessage: handleCustomBusinessMessage,
    ),
  );

  await OpenIM.iMManager.signalingManager.setSignalingListener(
    OnSignalingListener(
      onReceiveNewInvitation: handleIncomingCall,
      onInviteeAccepted: handleInviteeAccepted,
      onInviteeRejected: handleInviteeRejected,
      onInvitationCancelled: handleInvitationCancelled,
      onInvitationTimeout: handleInvitationTimeout,
      onInviteeAcceptedByOtherDevice: handleAcceptedElsewhere,
      onInviteeRejectedByOtherDevice: handleRejectedElsewhere,
      onHangup: handleHangup,
      onRoomParticipantConnected: handleParticipantConnected,
      onRoomParticipantDisconnected: handleParticipantDisconnected,
      onStreamChange: handleStreamChange,
      onReceiveCustomSignal: handleCustomSignal,
    ),
  );
}

ConversationGroupManager retains the conversation-group listener separately, so it is not configured again in this combined entry point. See Conversation groups overview for its complete registration, five callback types, and state-merging rules.

The pinned SDK does not expose corresponding remove or unset APIs. On sign-out, account switch, or state-layer disposal, stop dispatching callbacks to the old account and disposed widgets, and release the application's own references. After signing in again, overwrite the configurations with the complete listener set for the new account.

Event ownership

Event scopeMerge identifierComplete handling page
User profile and online statususerIDUser overview
Friends and blocklistuserIDRetrieve the friend list by page
Conversation listconversationIDRetrieve the conversation list
Conversation groupsconversationGroupIDConversation groups overview
Total unread countCurrent signed-in userMaintain the total unread count
Typing statusconversationID:userIDReport typing status
GroupsgroupIDGroup overview
Group membersgroupID:userIDGroup-member retrieval
Group applicationsgroupID:userIDGroup applications overview
New messagesconversationID:clientMsgIDReceive messages
Message deletionconversationID:clientMsgIDDelete a message
Message recallconversationID:clientMsgIDRecall a message
Message modificationconversationID:clientMsgIDModify a message
Pinned messagesconversationID; messages by clientMsgIDPin or unpin a message
One-to-one read receiptsconversationID:clientMsgIDMark a conversation as read
Custom business notificationsID or idempotency key from the business protocolReceive custom business messages
CallsroomID; participants also use user IDsCall events
Custom call signalsroomID:eventIDSend a custom signal

Listen for initial synchronization

The synchronization lifecycle also belongs to the application's single OnConversationListener. It describes SDK data synchronization and is not the Future callback of any query API.

void handleSyncStart(bool? reinstalled) {
  setSyncState(status: 'syncing', progress: 0, reinstalled: reinstalled == true);
}

void handleSyncProgress(int? progress) {
  setSyncState(status: 'syncing', progress: progress ?? 0);
}

void handleSyncFinish(bool? reinstalled) {
  setSyncState(status: 'ready', progress: 100, reinstalled: reinstalled == true);
  reloadVisibleSnapshots();
}

void handleSyncFailed(bool? reinstalled) {
  setSyncState(status: 'failed', reinstalled: reinstalled == true);
}

Use onSyncServerStart to enter the synchronizing state and onSyncServerProgress to update progress. After completion, re-query the snapshots required by the current UI. On failure, record the error and wait for retry or connection recovery. Always treat event increments, query snapshots, and Future completion as separate stages.