使用compose + navigation-compose时,跳转新页面后旧页面状态被销毁,如何保留?

例如:

@Composable
fun HomeScreen(
  navHostController: NavHostController
) {
  var content by remember { mutableStateOf("aaa") }

  Column {
    Text(content)
    Text("change content",
      modifier = Modifier
        .clickable { content = "bbb" }
    )
    
    // 跳转到article页面后,content的值丢失了,再回到home页面发现变成了初始值aaa
    Text("goto article screen",
      modifier = Modifier
        .clickable { navHostController.navigate("article") }
    )
  }
}

另外我还尝试了使用rememberSaveable,但是这个存储复杂对象需要手动实现stateSaver,一般为了视图和逻辑分离都要单独写一个类集中管理组件逻辑,就导致几乎所有带状态的组件都得手动实现stateSaver,非常麻烦。而且我感觉没有必要将还未关闭的页面状态序列化,请问还有什么办法能防止旧页面状态被销毁呢?

阅读 6.2k
1 个回答

研究出解决办法了,在navigation-compose的基础上用Hilt做ViewModel的依赖注入,Hilt会自动以每个compose路由为作用域生成唯一ViewModel实例,对于生命周期为整个页面的组件可以将状态提升到ViewModel里。如果要写在多个页面通用的带状态组件,方便从Bundle恢复的状态就用rememberSaveable,不容易恢复的状态或者是不想在重建时销毁的View实例,可以用CompositionLocal来做状态提升,每次重建先判断CompositionLocal有没有,有就取,没有就新建一个加进去,在Composable函数内用currentCompositeKeyHash可以取到当前组件在当前路由的唯一hash码,用这个再拼上一些自定义值组成一个id就可以作为存到CompositionLocal的key。生命周期要跟随页面CompositionLocalProvider就放在页面根层级,要在整个App的声明周期存在就放在MainActivity的setContent里,大概就是这些

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏