事件与错误处理
持续展示的数据优先订阅对应 StateFlow 或列表快照;事件适合触发提示、导航、诊断和临时消息处理,不应作为唯一数据存储。
订阅事件
import com.deeprespond.im.*
im.on<DREvent.MessageSendFailed>().collect { event ->
println("${event.clientMsgId}: ${event.error.code}")
}也可使用 im.on(DREvent.MessageReceived::class) 或收集全部 im.events。收集放在生命周期协程中,停止页面时取消。SharedFlow 的缓冲有限,不能将它作为永不丢失的业务消息队列。
启动阶段事件暂存给第一个订阅者,startupEvents 可读取并清空启动事件;建立统一订阅,避免多个页面各自消费同一启动导航。
事件分类
| 类别 | 主要事件 |
|---|---|
| 登录与连接 | AuthStateChanged、ConnectionStateChanged、SyncCompleted、SyncFailed |
| 存储与配置 | StorageReset、StorageFull、StorageModeChanged、ConfigChanged、SdkUpgradeRequired |
| 用户与设备 | MeChanged、MeMuteChanged、UsersChanged、DevicesChanged、DevicesNewLogin |
| 前后台与时区 | AppStateChanged、ClientStateReported、TimezoneChanged |
| 会话与消息 | ConversationsChanged、ConversationsUnreadChanged、MessagesChanged、MessageReceived、MessageSendFailed、MessageOnline、TypingChanged、ReceiptsChanged |
| 好友与群 | FriendsChanged、BlacklistChanged、FriendRequestsChanged、GroupsChanged、GroupMembersChanged、GroupRequestsChanged |
| 推送与在线 | PushChanged、PresenceChanged、PresenceSubscribeFailed |
| 通话 | CallIncoming、CallChanged、GroupCallChanged |
原生推送的 opened / registrations 和系统通话 actions 在各自控制器上,聊天室事件在房间句柄上。全部事件字段见数据类型。
DRException
import com.deeprespond.im.*
import kotlinx.coroutines.CancellationException
try {
im.messages.send(SendTarget.User("bob"), OutgoingContent.Text("你好"), SendOptions(waitUntilSent = true))
} catch (error: CancellationException) {
throw error // 保持 Kotlin 协程取消语义。
} catch (error: DRException) {
println("${error.code}/${error.reason}; request=${error.requestId}")
}| 字段 | 含义 |
|---|---|
| code、reason | 错误码及 details.reason,业务按它们判断 |
| details | 原始 JsonObject 附加信息 |
| source | HTTP、WS、LOCAL |
| status | HTTP 状态,长连接和本地失败可能为 null |
| requestId | 排查请求的 ID |
| retryAfter | Kotlin Duration;Java 用 retryAfterMillis |
常见本地错误:network_error、timeout、aborted、not_signed_in、not_connected、local_validation、storage_error、unsupported、permission_required、device_error、invalid_state、send_abandoned。服务端业务错误见错误码。
取消协程会抛 CancellationException,不包装成普通业务失败。持久写入已经发出或消息已经入队时,取消等待不撤销服务端操作;上传 / 下载任务有单独的 cancel。遇到 rate_limited 按 retryAfter 和实际策略处理,不要无限重试。
日志与诊断
LogOptions 支持 level、sink、file;SDK 默认 WARN,App 可开启文件日志或把 LogEntry 交给自己的日志系统。日志字段包含 module、code、reason、requestId、connectionId。
val info = im.connection.diagnostics()
val archive = im.exportDiagnostics()
println(info.connection)
println(archive.name)诊断包括连接、最近断线和失败、同步时间、存储模式、时钟偏差和发送队列大小。exportDiagnostics 返回缓存目录中的 ZIP,SDK 会清理过期文件;通过 App 的 FileProvider 分享,不要暴露私有绝对路径。日志和诊断用于排查,不应加入密码、凭证或消息正文。
describeError、renderRecall 等提示辅助见界面与生命周期。
频道状态
独立频道以 im.channels.current、handle.snapshot、handle.tracks 的 StateFlow 为界面状态来源,持续观察并在页面结束时取消。不要用原 CallIncoming / CallChanged 事件推断频道状态;频道没有呼叫振铃。取消加入协程会清理预留,HTTP 退出失败仍停止本地媒体,见频道接入。
