在 Jetpack Compose 中导航时记住列表项状态

Але*_*кий 2 android-jetpack-navigation android-jetpack-compose

如果我们为像 valstate = remember(it) { mutableStateOf(ItemState()) }这样的列表项创建状态,那么我们在滚动时会失去扩展状态。

如果我们在 LazyColumn 之前提升生成更高的状态,那么扩展状态将正确保存

 val states = items.map { remember(it) { mutableStateOf(ItemState()) } }
 LazyColumn(modifier = Modifier.fillMaxSize()) {....
Run Code Online (Sandbox Code Playgroud)

但是当我们展开一个项目时,点击按钮,转到详细信息屏幕,然后回到我们松开展开状态的项目。保存项目状态的最佳方法是什么?

 val states = items.map { remember(it) { mutableStateOf(ItemState()) } }
 LazyColumn(modifier = Modifier.fillMaxSize()) {....
Run Code Online (Sandbox Code Playgroud)

Com*_*are 6

但是,当我们展开一个项目时,单击按钮,转到详细信息屏幕,然后返回到我们松开展开状态的项目。

正确的。remember()记住特定构图的范围。这意味着它会记住整个重组,但不会记住该组合物被单独的组合物替换时的情况。就您而言,导航会Greeting()用合成替换您的合成DetailsScreen()

保存项目状态的最佳方法是什么?

进一步提升状态,达到不会被导航取代的组合。在这种情况下,这将是您的根组合,您可以在其中进行调用rememberNavController()

或者,将状态存储在视图模型中,该视图模型的范围仅限于您的活动,或者至少仅限于该根组合。

如果你想让这个状态在你的进程的生命周期之外持续存在,我认为我们应该使用效果通过存储库将状态保存到某个持久存储(例如,JSON 文件)并从该存储恢复状态。不过,我还没有尝试过这种方法。


Але*_*кий 6

使用rememberSaveable可以解决问题。

感谢/sf/users/99704461/

    LazyColumn(modifier = Modifier.fillMaxSize()) {
        items(items) { item ->
            val state = rememberSaveable(item) { mutableStateOf(ItemState()) }
    
            key(item) {
                Item(index = item,
                    state = state.value,
                    onClick = { onItemClick(item) },
                    modifier = Modifier
                        .fillMaxSize()
                        .clickable {
                            state.value.changeState()
                        }
                )
            }
            Divider()
        }
    }
Run Code Online (Sandbox Code Playgroud)