Events overview
Register OpenIM Flutter SDK listeners centrally and dispatch real-time events across application domains.
The OpenIM Flutter SDK delivers real-time notifications for connection state, background data synchronization, users, friendships, conversations, conversation groups, groups, messages, and VoIP calling via listeners. Each manager maintains only one active listener instance; invoking a setter again overwrites the previously registered instance in the Dart layer. Therefore, register all callbacks once within a centralized application state service during startup, and avoid re-registering listeners inside Widget build methods or individual page routes.
Centralized listener registration
The following entry point consolidates application-wide listener registrations. The full incremental merge logic for each handle* callback is documented in the dedicated topic pages listed in the table below.
Code example
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,
),
);
}The conversation group listener is maintained separately by ConversationGroupManager and is omitted from the consolidated entry point above. See Conversation groups overview for its registration, five callback types, and state merge rules.
The SDK does not provide explicit remove or unset APIs. When signing out, switching accounts, or destroying state layers, cease dispatching events to old user stores or unmounted widgets. When logging in with a new account, overwrite the active listeners with new callbacks.
Event domain mapping
| Domain | Entity Merge Key | Dedicated Documentation Page |
|---|---|---|
| User profile & online status | userID | Users overview |
| Friends & blocklist | userID | Get friend list with pagination |
| Conversation list | conversationID | Retrieve conversation list |
| Conversation groups | conversationGroupID | Conversation groups overview |
| Total unread message count | Current user | Get total unread count |
| Typing status | conversationID:userID | Update typing status |
| Groups | groupID | Groups overview |
| Group members | groupID:userID | Retrieving group members overview |
| Group join applications | groupID:userID | Group applications overview |
| New incoming messages | conversationID:clientMsgID | Receive messages |
| Message deletion | conversationID:clientMsgID | Delete saved message |
| Message revocation | conversationID:clientMsgID | Revoke a message |
| Message modification | conversationID:clientMsgID | Modify a message |
| Pinned messages | conversationID (messages by clientMsgID) | Pin or unpin message |
| C2C read receipts | conversationID:clientMsgID | Mark conversation as read |
| Custom business notifications | Payload business ID or idempotency key | Custom business listener |
| VoIP calls | roomID (participants by userID) | Handle call events |
| Custom call signaling | roomID:eventID | Send a custom signal |
Listen to initial synchronization
Synchronization callbacks belong to OnConversationListener. They describe background database synchronization progress with the server and are separate from query Future completions.
Code example
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 transition into a syncing state, and onSyncServerProgress to render progress bars. When onSyncServerFinish fires, reload the snapshots required by currently visible screens. If onSyncServerFailed triggers, record the failure and wait for connection recovery. Always handle asynchronous events, query results, and Future completions as distinct operational stages.
Was this page helpful?