我完全混淆了撰写概念。 我有代码
@Composable
fun HomeScreen(viewModel: HomeViewModel = getViewModel()) {
Scaffold {
val isTimeEnable by viewModel.isTimerEnable.observeAsState()
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
modifier = Modifier
.fillMaxSize()
.background(Color.Black),
) {
Switch(
checked = isTimeEnable ?: false,
onCheckedChange = {
viewModel.setTimerEnable(it)
},
)
Clock(viewModel.timeSelected.value!!) {
viewModel.setTime(it)
}
}
}
}
@Composable
fun Clock(date: Long, selectTime: (date: Date) -> Unit) {
NumberClock(Date(date)) {
val time = SimpleDateFormat("HH:mm", Locale.ROOT).format(it)
Timber.d("Selected time: time")
selectTime(it)
}
}
为什么当我点击开关时
Clock
小部件会重新组合。如果我从 selectTime(it)
中删除行 Clock
,则不会发生小部件回调重组。
撰写版本:1.0.2
这是因为就组合而言,您每次都在创建一个新的
selectTime
lambda,因此重新组合是必要的。如果你传递 setTime
函数作为引用,compose 就会知道它是同一个函数,因此不需要重新组合:
Clock(viewModel.timeSelected.value!!, viewModel::setTime)
remember
它。双括号 ({{ }}
) 在这里很重要,因为你需要记住 lambda。
Clock(
date = viewModel.timeSelected.value!!,
selectTime = remember(viewModel) {
{
viewModel.setTimerEnable(it)
}
}
)
rememberLambda
这将使你的代码更具可读性:
selectTime = rememberLambda(viewModel) {
viewModel.setTimerEnable(it)
}
请注意,您需要将所有可能更改的值作为键传递,因此
remember
将根据需要重新计算。
总的来说,重组并不是一件坏事。当然,如果您可以减少它,您应该这样做,但是即使您的代码被重组很多次,它也应该可以正常工作。例如,您不应该在可组合项内部进行大量计算来执行此操作,而应使用副作用。
因此,如果重新组合
Clock
导致奇怪的 UI 效果,则您的 NumberClock
可能存在问题,无法在重新组合后继续存在。如果是这样,请将 NumberClock
代码添加到您的问题中,以获取有关如何改进它的建议。
val updateClickedUser:(String,String,Boolean,Boolean)->Unit = remember(streamViewModel) { { username, userId, banned, isMod ->
streamViewModel.updateClickedChat(
username,
userId,
banned,
isMod
)
} }
ChatUI(
twitchUserChat = twitchUserChat,
updateClickedUser = { username, userId, banned, isMod ->
updateClickedUser(
username,
userId,
banned,
isMod
)
},
)
这是预期的行为。当用户切换开关时(通过调用 vm.setTimeenabled),您显然正在修改视图模型内的
isTimeEnabled
字段。现在,很明显,视图模型中的 isTimeEnabled
是一个 LiveData
实例,并且您通过在可组合对象中调用 observeAsState
来引用该实例。因此,当您修改开关的 onValueChange 中的值时,您实际上是在修改可组合项所依赖的状态。因此,为了呈现更新的状态,会触发重组