It is a video call screen . It needs token and channel name to work which needs to be passed to init call engine. I am storing these in a data class which is used as a mutable state.
Screen State Data class
@Keep
data class CallScreenState(
val callerId: Int? = null,
val recieverId: Int? = null,
val chatRoom: ChatRoom.Data? = null,
val rtcToken: AgoraTokenResponse.TokenData? = null
)
And in viewmodel initializing state by this code :
var callScreenState by mutableStateOf(CallScreenState())
and in viewmodel on success response of chat room and token api the state is updated with this code.
callScreenState = callScreenState.copy(
chatRoom = chatRoom.data,//from response
rtcToken = token.data //from response
)
From here it is expected to recompose the screen with new updated value of chatRoom and rtcToken.
And in composable
val screenState = remember {
viewModel.callScreenState
}
this screen state is used to pass values to the init engine
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
)
}
This is the initEngine function creation
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)
}
I understand at the very beginging, channel name and token inside the screen state is empty that is before the api call . Once api for getting token and chat room gives succes , the screen state updated from viewmodel and i expect the initEngine fun to be called again as it should recompose. But it is not. Am I Missing something ? How to make it recompose whenver the channelname value inside screen sctate changes?
CodePudding user response:
I can't understand your entire use-case but have you tried specifying a key
to your remember
?
How to make it recompose whenver the channelname value inside screen sctate changes?
You can try either of these, though I'm not sure if they would solve your problem, but when you supply a key
to remember
and it changes, it will re-calculate
, assuming the channelName
that has been calculated by remember
previously will be different on the next pass.
This,
val screenState = remember(key1 = channelname) {
viewModel.callScreenState
}
or this
val mEngine = remember(key1 = channelname) { ... }