Skip to content

事件与回调

本页是接入规则和完整事件速查表。需要逐个回调查看载荷字段、准确触发条件、 可靠性、关联 API 和页面处理代码时,进入 回调详细说明;每个公开方法的代码请在 逐个 API 参考中选择当前平台查看。

1. 订阅入口

events.subscribe

平台入口取消订阅
iOSclient.addEventListener { event in ... }XHIMEventListenerToken.cancel() 或释放 token
macOSclient.addEventListener { event in ... }XHIMEventListenerToken.cancel() 或释放 token
Androidclient.events.collect { event -> ... }取消收集它的 Coroutine
Windowsawait foreach (var evt in client.Events(token))取消 CancellationToken
HarmonyOSconst off = client.onEvent(listener)调用返回的 off()
Flutterclient.events.listen(listener)取消 StreamSubscription
Electronclient.onAccountStateChanged(listener) / client.onEvent(listener)调用返回的取消函数
Webclient.on('accountStateChanged', listener)调用返回的取消函数

iOS、macOS 和 Windows 还提供只包含 durable projection invalidation 的 projectionEvents / ProjectionEvents()。Android 和 HarmonyOS 从统一 XHIMEvent 流筛选对应类型。

iOS 与 macOS 回调都在 MainActor 上按事件顺序执行:

swift
private var eventToken: XHIMEventListenerToken?

eventToken = client.addEventListener { [weak self] event in
    if case .conversationChanged = event {
        self?.reloadConversations()
    }
}

Swift Concurrency 项目仍可使用 for await event in client.events,取消消费 Task 即退订。

应当先订阅,再执行首次查询,避免订阅与首屏查询之间出现窗口:

text
install subscriber → query initial page → consume events → re-query

2. 完整事件表

统一事件载荷何时产生接入方动作
stateChangedXHIMClientState生命周期变化更新连接提示;到 ready 再允许写操作
messageQueued消息接受回执 payload本地 Outbox 接受新消息按 client message ID 重查消息
messageRetryQueued回执 payload失败消息重新入队重查消息状态
messageCancelled回执 payload待发送消息被取消重查消息状态
conversationReadChangedconversationID已读水位改变重查会话和总未读
messageMutatedclientMessageID编辑或撤回完成重查目标消息
reliableBusinessNotificationReceivedowned XHIMReliableBusinessNotification可靠回调通知已提交本地 Sync 游标执行业务回调;不要写入聊天、未读或日志
mediaTaskUpdatedXHIMMediaTaskUpdate媒体任务状态变化以 task ID 查询完整任务
messageUpsertedXHIMProjectionChange消息投影新增/替换重查对应会话时间线
messageLocallyDeletedXHIMProjectionChange当前设备新增本地删除 tombstone重查对应会话时间线
messageStateChangedXHIMProjectionChange消息投递状态变化重查对应消息
conversationChangedXHIMProjectionChange会话摘要、未读、偏好改变重查会话页
socialChangedXHIMProjectionChange好友/群组/黑名单投影改变socialScope 重查
syncAppliedXHIMProjectionChange一批远端同步完成刷新当前页面依赖的投影
presenceChangedXHIMPresenceUpdate用户在线状态变化显示并按 expiresAt 本地过期
typingChangedXHIMTypingUpdate会话输入状态变化显示并按 expiresAt 本地过期
customSignalReceivedXHIMCustomSignal会话成员发布在线临时信令校验 type/version 并按 expiresAt 本地过期
accountStateChangedXHIMAccountStateChange服务端权威账号状态导致会话失效终止请求和自动续凭,清理账号容器并回到登录页
projectionInvalidatedXHIMProjectionChange遇到未来 schema / kind完整重查相关页面,不解析未知值

平台类型名称:

统一事件iOSmacOSAndroidWindowsHarmonyOS
state.stateChanged.stateChangedXHIMEvent.StateChangedXHIMEvent.StateChangedXHIMStateChangedEvent
queued.messageQueued.messageQueuedXHIMEvent.MessageQueuedXHIMEvent.MessageQueuedXHIMMessageQueuedEvent
retry queued.messageRetryQueued.messageRetryQueuedXHIMEvent.MessageRetryQueuedXHIMEvent.MessageRetryQueuedXHIMMessageRetryQueuedEvent
cancelled.messageCancelled.messageCancelledXHIMEvent.MessageCancelledXHIMEvent.MessageCancelledXHIMMessageCancelledEvent
read.conversationReadChanged.conversationReadChangedXHIMEvent.ConversationReadChangedXHIMEvent.ConversationReadChangedXHIMConversationReadChangedEvent
mutated.messageMutated.messageMutatedXHIMEvent.MessageMutatedXHIMEvent.MessageMutatedXHIMMessageMutatedEvent
media.mediaTaskUpdated.mediaTaskUpdatedXHIMEvent.MediaTaskUpdatedXHIMEvent.MediaTaskUpdatedXHIMMediaTaskUpdatedEvent
message upsert.messageUpserted.messageUpsertedXHIMEvent.MessageUpsertedXHIMEvent.MessageUpsertedXHIMMessageUpsertedEvent
message locally deleted.messageLocallyDeleted.messageLocallyDeletedXHIMEvent.MessageLocallyDeletedXHIMEvent.MessageLocallyDeletedXHIMMessageLocallyDeletedEvent
message state.messageStateChanged.messageStateChangedXHIMEvent.MessageStateChangedXHIMEvent.MessageStateChangedXHIMMessageStateChangedEvent
conversation.conversationChanged.conversationChangedXHIMEvent.ConversationChangedXHIMEvent.ConversationChangedXHIMConversationChangedEvent
social.socialChanged.socialChangedXHIMEvent.SocialChangedXHIMEvent.SocialChangedXHIMSocialChangedEvent
sync.syncApplied.syncAppliedXHIMEvent.SyncAppliedXHIMEvent.SyncAppliedXHIMSyncAppliedEvent
presence.presenceChanged.presenceChangedXHIMEvent.PresenceChangedXHIMEvent.PresenceChangedXHIMPresenceChangedEvent
typing.typingChanged.typingChangedXHIMEvent.TypingChangedXHIMEvent.TypingChangedXHIMTypingChangedEvent
custom signal.customSignalReceived.customSignalReceivedXHIMEvent.CustomSignalReceivedXHIMEvent.CustomSignalReceivedXHIMCustomSignalReceivedEvent
account state.accountStateChanged.accountStateChangedXHIMEvent.AccountStateChangedXHIMEvent.AccountStateChangedXHIMAccountStateChangedEvent
invalidated.projectionInvalidated.projectionInvalidatedXHIMEvent.ProjectionInvalidatedXHIMEvent.ProjectionInvalidatedXHIMProjectionInvalidatedEvent

Flutter 的对应类型是 XHIMAccountStateChanged;Electron 是 XHIMElectronAccountStateChange;Web 是 XHIMWebAccountStateChanged。三端都会在 Facade 边界深拷贝事件并屏蔽 IPC/网络中未公开的未知字段。

2.1 账号状态事件的严格规则

accountStateChanged 只表示以下固定事实:

  • stateactive / suspended / unregistered / unknown
  • kickedReasonnone / account_suspended / account_unregistered
  • revision:正整数是服务端权威版本;0 表示旧实时 frame 没有 revision,不得伪装成当前最新版本;
  • accountEpochconnectionGeneration:限定事件属于当前登录账号与 当前连接代次。

Facade 会丢弃旧账号 epoch、退出/关闭后迟到、以及重复或低 revision 事件。revision 为 0 时只做同一状态+原因的保守去重。 普通 SESSION_REVOKED 仍保持原会话撤销语义;只有精确的 account_suspended / account_unregistered 才生成强类型账号事件。 管理员填写的原因不属于 SDK 模型,不会下发给客户端。

3. Projection change 字段

XHIMProjectionChange 是轻量失效通知,不是完整业务对象:

字段用途
schemaVersion事件结构版本
kind / nativeKind已知类型与未修改原始值
origin / nativeOriginlocal、remoteSync、outbox、未来值
socialScope好友申请、好友、群、群成员、黑名单、入群申请
messageState消息状态变更时的已知状态
accountEpoch区分登录账号生命周期
connectionGeneration区分重连代次
projectionRevision每 Client 单调失效序号;跳号意味着重查
entityRevision相关实体 revision
sequence消息/同步服务端序号
affectedCount批量变更影响数量
各种 ID缩小重查范围;空值表示需要扩大刷新

只要 requiresFullRequery 为 true、revision 不连续或 scope 为空,就重新查询 当前页面依赖的完整投影。不要尝试回放事件补数据库。

4. UI 线程规则

原生 Core 在 XHIM 私有串行 callback 线程产生 Completion 和 Event。各 Facade 会先复制 native borrowed bytes,再恢复平台异步调用;但恢复位置不保证是 UI 线程。

  • iOS/macOS:回调式 Facade 已切到 MainActor;直接消费 AsyncStream 时使用 await MainActor.run@MainActor ViewModel;
  • Android:在 ViewModel Scope 中收集,写 UI state 时使用 Main dispatcher;
  • Windows:根据 UI 框架切回 Dispatcher;
  • HarmonyOS:在 UIAbility/组件允许的任务上下文更新状态。

Callback 中可以提交新的异步请求,但不能同步阻塞等待另一个 XHIM callback。

5. 普通请求取消

普通请求取消只取消一次异步操作的等待/执行许可,不撤销已经提交的服务端业务 事实:

swift
let request = client.searchMessages(
    query,
    limit: 50,
    onSuccess: { page in self.show(page.messages) },
    onFailure: { error in self.show(error.message) }
)
request.cancel()

Swift Concurrency 调用则取消承载请求的 Task

kotlin
val job = scope.launch { client.searchMessages(query, limit = 50) }
job.cancel()
csharp
using var cts = new CancellationTokenSource();
var task = client.SearchMessagesAsync(query, limit: 50, cts.Token);
cts.Cancel();
ts
let requestId: bigint = 0n
const pending = client.searchMessages(query, undefined, 50,
  (id: bigint) => requestId = id)
client.cancelRequest(requestId)
await pending

取消结果使用稳定 CANCELLED 错误。已经由 Outbox 接受的消息要用 cancelMessage;持久化媒体任务要用 cancelMediaTask

6. 自动续凭回调

credentialRequired 不单独暴露给页面做 Token 逻辑。一键 connect 安装的 Business Provider 会在账号容器内自动处理:

text
state credentialRequired
  → SDK 合并并发刷新
  → 调用业务 Provider
  → updateCredential
  → reconnect + sync
  → ready

Provider 失败时保留原始稳定错误。UI 只根据 userAction 决定显示“重试登录” 或回到 App 登录页,不记录凭证文本。

XHIM 客户端 SDK 与服务端文档