我有以下 UI 结构:
家长懒专栏:
TvLazyColumn(){
itemsIndexed(rows){index, row ->
MyLazyRow(mainViewModel, row, index)
}
}
MyLazyRow.kt:
@Composable
fun MyLazyRow(mainViewModel : MainViewModel, row : List<rowItem>, listIndex : Int){
val myLazyState = rememberTvLazyListState()
val myRequesters by remember(row.size) { derivedStateOf { Array(row.size) { FocusRequester() } } }
TvLazyRow(state = myLazyState){
itemsIndexed(row){ index, rowItem ->
MyItem(item = rowItem, modifier = Modifier.focusRequester(myRequesters[index]))
}
}
LaunchedEffect(Unit){
if (listIndex == mainViewModel.getLastFocussedRow.value){
try {
myLazyState.scrollToItem(dummyTargetFocus) //some randomly set const val
myRequesters[dummyTargetFocus].requestFocus()
} catch (ex: Exception) {
ex.printStackTrace()
}
}
}
}
从代码中可以看出,我试图将焦点集中到 LazyRow 之一中的一张随机卡上,但是当 LaunchedEffect() 内的代码运行时,它会抛出相同的错误:
androidx.compose.runtime.LeftCompositionCancellationException: 协程作用域离开了组合
即使在确保我们请求焦点的可组合项:(惰性行和项目)位于屏幕上并且在焦点请求时已组合好。导致此错误的原因可能是什么?我可以有其他解决方法来解决此问题吗?
此异常仅意味着协程作用域被取消,因为
LaunchedEffect
已从“屏幕”中删除。基本上,如果该行因为不再可见而被回收,则 LaunchedEffect
的协程范围将被取消。这是预期的行为,因为您不希望 UI 元素启动比 UI 元素本身寿命更长的后台任务。
如果这是您想要的,您还可以在
rememberCoroutineScope()
之外使用 LazyColumn
,此范围将保持活动状态,直到 UI 的这一部分被删除,但在回收行时不会停止。
您的代码暗示您希望取消工作,但错误消息显示在日志中。您可以执行以下操作:
try {
...
} catch (e: CancellationException) {
// Ignore
} catch (e: Exception) {
...
}