這是一個視頻通話螢屏。它需要令牌和通道名稱才能作業,需要將其傳遞給 init 呼叫引擎。我將這些存盤在一個用作可變狀態的資料類中。
螢屏狀態資料類
@Keep
data class CallScreenState(
val callerId: Int? = null,
val recieverId: Int? = null,
val chatRoom: ChatRoom.Data? = null,
val rtcToken: AgoraTokenResponse.TokenData? = null
)
并在視圖模型初始化狀態下通過此代碼:
var callScreenState by mutableStateOf(CallScreenState())
并且在關于聊天室和令牌 api 的成功回應的視圖模型中,狀態會使用此代碼進行更新。
callScreenState = callScreenState.copy(
chatRoom = chatRoom.data,//from response
rtcToken = token.data //from response
)
從這里開始,預計將使用 chatRoom 和 rtcToken 的新更新值重新組合螢屏。
在可組合的
val screenState = remember {
viewModel.callScreenState
}
此螢屏狀態用于將值傳遞給初始化引擎
val mEngine = remember {
initEngine(
context,
object : IRtcEngineEventHandler() {
override fun onJoinChannelSuccess(channel: String?, uid: Int, elapsed: Int) {
Timber.e("hhp-CallScreen onJoinChannelSuccess channel:$channel,uid:$uid,elapsed:$elapsed")
}
override fun onUserJoined(uid: Int, elapsed: Int) {
Timber.e("hhp-CallScreen onUserJoined:$uid")
val desiredUserList = remoteUserMap.toMutableMap()
desiredUserList[uid] = null
remoteUserMap = desiredUserList.toMap() as HashMap<Int, TextureView?>
}
override fun onUserOffline(uid: Int, reason: Int) {
Timber.e("hhp-CallScreen onUserOffline:$uid")
val desiredUserList = remoteUserMap.toMutableMap()
desiredUserList.remove(uid)
remoteUserMap = desiredUserList.toMap() as HashMap<Int, TextureView?>
}
override fun onNetworkQuality(uid: Int, txQuality: Int, rxQuality: Int) {
Timber.e("hhp-CallScreen onNetworkQuality $uid $txQuality $rxQuality")
}
},
screenState.chatRoom?.channelName ?: "", //Not recomposing when value changes in viewmodel
viewModel.userRole,
token = screenState.rtcToken?.token ?: "" //Not recomposing when value changes in viewmodel
)
}
這是initEngine函式創建
fun initEngine(
current: Context,
eventHandler: IRtcEngineEventHandler,
channelName: String,
userRole: String,
token: String
): RtcEngine =
RtcEngine.create(current, BuildConfig.AGORA_APPID, eventHandler).apply {
enableVideo()
setChannelProfile(1)
if (userRole == "Broadcaster") {
setClientRole(1)
} else {
setClientRole(0)
}
//Expected to be recomposed when screen state value updated with new values
joinChannel(token, channelName, "", 0)
}
我一開始就明白,螢屏狀態中的頻道名稱和令牌在 api 呼叫之前是空的。一旦用于獲取令牌和聊天室的 api 成功,螢屏狀態就會從 viewmodel 更新,我希望再次呼叫 initEngine fun,因為它應該重新組合。但事實并非如此。我錯過了什么嗎?每當螢屏 sctate 中的 channelname 值發生變化時,如何使其重新組合?
uj5u.com熱心網友回復:
我無法理解您的整個用例,但您是否嘗試過key為您的remember?
每當螢屏 sctate 中的 channelname 值發生變化時,如何使其重新組合?
您可以嘗試其中任何一個,盡管我不確定它們是否會解決您的問題,但是當您提供一個keytoremember并且它發生變化時,它會re-calculate,假設先前計算channelName使用的remember's那個在下一個中會有所不同re-composition。
這個,
val screenState = remember(key1 = channelname) {
viewModel.callScreenState
}
或這個
val mEngine = remember(key1 = channelname) { ... }
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/525289.html
