介面與生命週期
SDK 不提供完整的聊天介面元件。無論用 Activity、Fragment、ViewModel 還是 Compose,都是訂閱同樣的 Flow 狀態、列表和訊息控制代碼。本頁講怎樣讓這些訂閱跟隨介面的生命週期,以及哪些資源要在頁面結束時釋放。
| 要做什麼 | 看哪裡 |
|---|---|
| 在 Activity / Fragment 中顯示會話列表 | Activity / Fragment |
| 訊息頁的訂閱和已讀 | 訊息頁 |
| 在 Compose 中使用 | Compose |
| 顯示名字、群提示、撤回提示 | 顯示輔助 |
| 頁面結束時要釋放什麼 | 資源歸屬 |
Activity / Fragment
引入 lifecycle-runtime-ktx,在 LifecycleOwner 處於 STARTED 時收集。Fragment 中用 viewLifecycleOwner,以免檢視銷燬後還在更新舊的介面。
kotlin
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import kotlinx.coroutines.launch
import com.deeprespond.im.*
fun observeConversations(owner: LifecycleOwner, im: DRClient) {
owner.lifecycleScope.launch {
owner.repeatOnLifecycle(Lifecycle.State.STARTED) {
im.conversations.listFlow().collect { snapshot ->
println(snapshot.items.size) // 更新会话列表。
}
}
}
}listFlow()在收集時建立列表、停止時釋放。需要自己呼叫loadMore時,改為建立LiveList,並用try/finally關閉。- 要同時收集幾個
StateFlow時,在repeatOnLifecycle中分別launch:第一個collect不會結束,寫在它後面的第二個永遠不會執行。
訊息頁
kotlin
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import kotlinx.coroutines.launch
import com.deeprespond.im.*
fun observeMessages(owner: LifecycleOwner, im: DRClient, conversationKey: String) {
owner.lifecycleScope.launch {
owner.repeatOnLifecycle(Lifecycle.State.STARTED) {
val list = im.messages.open(conversationKey)
try {
list.setViewing(atBottom = true, visible = true)
list.snapshot.collect { snapshot -> println(snapshot.items.size) }
} finally {
list.setViewing(visible = false)
list.close()
}
}
}
}示例中把“停在最新處”固定為 true;實際頁面在滾動時更新 atBottom,頁面不顯示時把 visible 設為 false。取消狀態的收集不會離開聊天室或結束通話通話,這些要按你的頁面跳轉邏輯單獨處理。
Compose
- 引入生命週期的 Compose 適配庫,用
collectAsStateWithLifecycle讀取StateFlow。 listFlow()可以直接收集。自己開啟的MessageList在remember中按會話鍵建立、在DisposableEffect中關閉,並按生命週期設定visible。不要在重組時反覆呼叫messages.open。- 列表項的穩定鍵:會話用
conversationKey;訊息用clientMsgId,訊息發出、有了正式的序號之後也要保持是同一個檢視;群成員和好友用username。 - 快照只用於讀取。修改資料請呼叫 SDK 的方法,不要直接改
raw或快照中的列表。
顯示輔助
kotlin
import com.deeprespond.im.render.*
val title = conversationTitle(im, conversation)
val sender = displayName(im, "bob", groupId)
val summary = summarize(im, message, groupId)
println("$title / $sender / $summary")displayName按好友備註、群暱稱、暱稱、使用者名稱的順序取第一個非空的。renderTip生成群提示的文字,renderRecall生成撤回提示,renderCallRecord生成通話記錄的文字;DRLocale.zhCN提供中文文案,describeError把錯誤轉成提示文字。這些函式只負責顯示,能否操作仍由介面決定。- 圖片用
DRImage和addDRImage,見 Coil 接入;影片用DRCallVideoView,頁面結束時unbind。 - 檢視大圖、下載和分享檔案,由 App 自己的頁面、儲存和 FileProvider 處理。
資源歸屬
| 資源 | 頁面或任務結束時 |
|---|---|
LiveList、MessageList | close() |
presence.subscribe | 關閉返回的 AutoCloseable |
事件和狀態的 Flow | 取消對應的協程 |
keepForeground() 返回的控制代碼 | close() |
| 已進入的聊天室 | 要離開時 room.leave() |
| 上傳、下載 | 真正要取消時呼叫 task.cancel();只取消等待不會停止任務 |
| 影片檢視 | unbind() |
| 整個客戶端 | 只在切換應用或徹底關閉時 destroy() |
頻道影片與收尾
獨立頻道的影片用 im-call 中的 DRChannelVideoView,只繫結 tracks 給出的 ChannelTrack,支援 FIT / FILL 和映象。頁面退出時:停止觀察 StateFlow,unbind 檢視,並在一個能執行完的協程中呼叫 handle.leave()。只銷毀 View 不會離開頻道。見頻道影片。
