我有一个关于StateFlow和用户界面重组的问题.简而言之,我的ViewModel有三个流程:

accountFlow,用于从数据库中获取当前登录的账号.

timelinePositionFlow,用于从当前登录的账号中检索最后一条浏览位置记录.

timelineFlow,它包含数据库中存储的当前登录帐户的所有帖子.

我面临的问题是,我的应用程序可以在多个账户之间切换,并浏览信息.因 for each 帐户都有一个存储的时间线位置,所以我需要使用rememberLazyListState(initialFirstVisibleItemIndex = ...)来初始化LazyColumn的位置.但是,如果我切换帐户,并且StateFlow发出新帐户的值,则rememberLazyListState不会重新组合.因此新账户的时间线大小可能只有20,而旧账户的时间线位置索引大于20,这将导致java.lang.IndexOutOfBoundsException错误 有没有解决这个问题的好办法?

视图模型

  private val activeAccountFlow = accountDao
    .getActiveAccountFlow()
    .filterNotNull()
    .distinctUntilChanged { old, new -> old.id == new.id }

  val timelinePosition = activeAccountFlow
    .mapLatest { TimelinePosition(it.firstVisibleItemIndex, it.offset) }
    .stateIn(
      scope = 视图模型Scope,
      started = SharingStarted.WhileSubscribed(),
      initialValue = TimelinePosition()
    )

  val timeline = activeAccountFlow
    .flatMapLatest { timelineDao.getStatusListWithFlow(it.id) }
    .map { splitReorderStatus(it).toUiData().toImmutableList() }
    .stateIn(
      scope = 视图模型Scope,
      started = SharingStarted.WhileSubscribed(),
      initialValue = persistentListOf()
    )

用户界面

  val timeline by 视图模型.timeline.collectAsStateWithLifecycle()
  val timelinePosition by 视图模型.timelinePosition.collectAsStateWithLifecycle()

  val lazyState = rememberLazyListState(
    initialFirstVisibleItemIndex = timelinePosition.index,
    initialFirstVisibleItemScrollOffset = timelinePosition.offset
  )

  LazyColumn { ... }

推荐答案

try 手动保存LazyListState.通过将第一个参数rememberSaveable设置为timelinePosition,当timelinePosition更改时,lazyState将重置.

    val lazyState = rememberSaveable(timelinePosition, saver = LazyListState.Saver) {
        LazyListState(timelinePosition.index, timelinePosition.offset)
    }

一百零八 如果在lazyState更改时更新timelinePosition,则此方法将不起作用,因为它将引入循环依赖.在这种情况下,我建议改变你获得timelinePosition英镑的方式.你并不真的需要StateFlow,因为当活跃用户发生变化时,你只需要阅读一次.在accountDaoViewModel上添加一次暂停方法,以获得timelinePosition,并在timeline发生变化时使用它,类似于:

    LaunchedEffect(timeline) {
        timelinePosition = viewModel.getTimeLinePosition(activeUserId)
        lazyState.animateScrollToItem(timelinePosition.index, timelinePosition.offset)
    }

Android相关问答推荐

使用Retrofit2的API调用:我如何能够一直进行API调用,以更新数据而无需重新打开应用程序

NativeScript在`ns run android`上重复Kotlin类

Jetpack创作动画断断续续变化的观点

Kotlin Android VS Kotlin多平台

从安卓S原生库的资源中读取json文件

Android手柄注射周期错误,多个模块引用一个核心模块

如何在Android中打印到命令行

在更改MuableState的值后,Android API 26(Oreo)上的Composable不能重新组合

如何在Jetpack Compose中将对象的移动从一个路径平滑地切换到另一个路径?

从包含的(复合)模块导入 Kotlin 类时,Android 应用程序模块的 build.gradle.kts 未解决的引用错误

减少Compose中可滚动选项卡之间的间距

可从 Play store 下载链接访问未发布的应用

ArrayList 上的 Android intent.getParcelableArrayListExtra 引发 Nullpointer 异常

Kotlin File(path).walkTopDown() 找不到文件

单击过go 的文章时 NewsApp 崩溃

Android:为什么 ICICI iMobile Pay 应用程序在我的应用程序中显示root/jailbroken设备?

将生成的 AAR 与 Composables 一起使用时未解决的参考

无法将片段中的 recyclerview 与适配器连接

在 Android Studio 中自动在多台设备上运行应用

需要一些关于开发者控制台上的 beta/alpha 测试的说明