这是一个视频呼叫屏幕。它需要令牌和通道名称来工作,需要传递到初始化调用引擎。我将这些存储在一个数据类中,用作可变状态。
屏幕状态数据类
@Keep
data class CallScreenState(
val callerId: Int? = null,
val recieverId: Int? = null,
val chatRoom: ChatRoom.Data? = null,
val rtcToken: AgoraTokenResponse.TokenData? = null
)
而在viewmodel中初始化状态由以下代码实现:
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
}
此屏幕状态用于将值传递到init引擎
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功能将被再次调用,因为它应该重新组合。但事实并非如此。我是否遗漏了什么?如何在屏幕状态中的通道名称值发生变化时重新组合?
1条答案
按热度按时间pdtvr36n1#
我不能理解您的整个用例,但是您是否尝试过将
key
指定给您的remember
?如何在屏幕状态中的channelname值改变时重新组合?
您可以尝试这两种方法中的任何一种,虽然我不确定它们是否能解决您的问题,但是当您向
remember
提供一个key
时,它发生了变化,它将是re-calculate
,假设remember's
先前计算所使用的channelName
在下一个re-composition
中将是不同的。这,
或此