[英]Jetpack Compose passing LiveData to a Composable lambda
我无法理解为什么我观察到我的值,因为 state 已正确传递到可组合 lambda 中,但不会触发可组合重构。
这是我的设置。
@Composable
fun Screen(
showBottomSheet: (@Composable () -> Unit) -> Unit,
viewModel: MyViewModel = hiltViewModel()
) {
val someValue = viewModel.someValue.observeAsState().value
MyController(
onShowBottomSheetClick = {
showBottomSheet {
Log.d("DEBUG", "value updated: $someValue")
BottomSheetLayout(
someValue = someValue,
onUpdateClick = { newValue -> viewModel.setValue(newValue) }
)
}
}
)
}
@Composable
fun MyController(
onShowBottomSheetClick: () -> Unit
) {
Text(
text = "show BottomSheet",
modifier = Modifier.clickable { onShowBottomSheetClick() }
)
}
@Composable
fun BottomSheetLayout(
someValue: Int,
onUpdateClick: (Int) -> Unit
) {
Text(
text = "Some value: $someValue",
modifier = Modifier.clickable { onUpdateClick(someValue + 1) }
)
}
@HiltViewModel
class MyViewModel @Inject constructor(): ViewModel() {
private val _someValue: Int? = MutableLiveData(null)
val someValue: LiveData<Int?> = _someValue
fun setValue(newValue: Int) {
_someValue.value = newValue
}
}
当我运行它并看到 output 时,日志没有显示更新的someValue
。
value updated: 0
value updated: 0
value updated: 0
但是,如果我将新的 state 值添加到 lambda 本身,它就可以正常工作。
// Screen
// ..
showBottomSheet {
val currentValue = viewModel.someValue.observeAsState().value // <-- Note the difference
Log.d("DEBUG", "value updated: $currentValue")
BottomSheetLayout(
someValue = currentValue,
onUpdateClick = { newValue -> viewModel.setValue(newValue) }
)
}
// ..
当我运行它并看到 output 时,日志显示正确更新的值。
value updated: 0
value updated: 1
value updated: 2
为什么会这样? 有什么办法可以将第一个 state 值传递给showBottomSheet
可组合 lambda?
先感谢您。
Log.d 是一个副作用,应该与它的一个处理程序一起使用。
@Composable
fun Screen(
showBottomSheet: (@Composable () -> Unit) -> Unit,
viewModel: MyViewModel = hiltViewModel()
) {
val someValue = viewModel.someValue.observeAsState().value
LaunchedEffect(someValue) {
Log.d("DEBUG", "value updated: $someValue")
}
MyController(
onShowBottomSheetClick = {
showBottomSheet {
BottomSheetLayout(
someValue = someValue,
onUpdateClick = { newValue -> viewModel.setValue(newValue) }
)
}
}
)
}
我没有尝试过你的代码,但这看起来像是这个问题中范围重组的效果。 在那个问题中,即使没有记住 mutableState 值也会更新,因为外部 scope 没有重组。 在您的情况下,因为您传递的是 value 而不是 state 因为没有触发重组而没有更新。
为什么没有记忆的 mutableStateOf 有时会起作用?
@Composable
fun Screen(
showBottomSheet: (@Composable () -> Unit) -> Unit,
viewModel: MyViewModel = hiltViewModel()
) {
val someValue = viewModel.someValue.observeAsState().value
MyController(
onShowBottomSheetClick = {
showBottomSheet {
Log.d("DEBUG", "value updated: $someValue")
BottomSheetLayout(
someValue = someValue,
onUpdateClick = { newValue -> viewModel.setValue(newValue) }
)
}
}
)
}
在此代码中,仅重构了showBottomSheet
,并且由于MyController
scope 中没有重构,因此作为值的 someValue 未更新。
使用此代码,我假设showBottomSheet
是可组合的,因为您可以调用 @Composable function Flow.collectAsState 您正在重新组合内部的所有内容,这就是为什么它使用viewModel.someValue
的最新值重新组合
showBottomSheet {
val currentValue = viewModel.someValue.observeAsState().value // <-- Note the difference
Log.d("DEBUG", "value updated: $currentValue")
BottomSheetLayout(
someValue = currentValue,
onUpdateClick = { newValue -> viewModel.setValue(newValue) }
)
}
这将您的值包装到State<T>
与remember API
的方式相同,因此每次您的值更改时都会导致重新组合。
val someValue by viewModel.someValue.observeAsState()
在您的示例中,state 由于.value
而立即转换,并且未调用重组。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.