TLDR:我今天大部分时间都在为DataStore个对象而战,更具体地说,为什么大多数Suspend方法似乎永远挂起,只有map {}.first个方法能让我获得Preferences对象.


上下文

我正在编写一个使用非常轻量级的本地存储的小型Android应用程序:

  1. 我需要在应用程序启动时从本地存储中读取所有设置(不需要阻止).
  2. 当用户与应用程序交互时,更新本地存储.不需要再看书了.

实例

最终奏效的是:

val preferences =
            context.transliterationStatesDataStore.data.firstOrNull() ?: return
val preferences =
            context.dataStore.data.map { preferences -> preferences }
                .first()

我以前试过的方法:

val preferences =
            context.dataStore.data.map { preferences -> preferences }
                .lastOrNull() ?: return
val preferences =
            context.dataStore.data.lastOrNull() ?: return
Log.d("debug", context.dataStore.data.count().toString())

混乱

我搞不懂为什么:

  1. .count()不起作用(永远暂停)
  2. .lastOrNull()不起作用(永远暂停)
  3. 当我想要的是磁盘中Preferenceslatest版本时,读取流的first值感觉是错误的.

有一个相关的问题here,但除了作者提供的更多数据点外,它没有收到任何答案.

推荐答案

来自数据存储区的流是无限的,因为它永久监视存储,因此每次值更改时都可以发出.因为它是无限的,所以收集流直到其最终值以获得其总和count(无穷大)或last值(永远不会到来)的函数将永远挂起.

资金流动是冷淡的.当您调用first(),then时,该流查询数据存储以获取要发出以供收集的当前值.它将是最新的值.first()是仅获取最新值的正确方法.如果您希望在发布新值时不断对最新值做出react ,则可以使用collect { }而不是first().

你会发现,大多数流量是无限的,如果它们是monitor,比如存储或数据库.例如,Room数据库函数返回的流都是无限的,就像从Datastore返回的流一样.

Android相关问答推荐

如何正确增加LazyStream中的变量

Android编写动画在发布版本中崩溃

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

如何在停止和销毁时更改函数中Firebase实时数据库的子项的值我试过了,但这不起作用.请使用Kotlin

Kotlin Android VS Kotlin多平台

如何从URI中获取图像大小

如何在这段代码android jetpack compose中实现全屏滚动

Android 应用程序从 Android Studio 安装,但不是作为 .apk 在外部安装.抛出java.lang.UnsatisfiedLinkError

Android AGP 8 + Gradle 8 + Kotlin 1.8 导致 Kapt 出错

如何在没有人窃取令牌的情况下使用我的移动应用程序中的 API

Android:ActivityCompat.requestPermissions 不显示弹窗(Android 13,targetSdkVersion=33)

如何正确地将图像上传到 Jetpack Compose 中的 LazyList 中的项目?

如何在 BasicTextField 中全选焦点

如何从日期 Select 器计算年龄?

Jetpack Compose Material3 禁用 ListItem

这是 let 函数的正确用法吗?

Android Material Date Range Picker - 如何仅更改所选范围日期的文本 colored颜色 ?

如何在 Android Studio 中使用 Github Copilot?

Android Studio (Kotlin):无法启动活动

Google Play 服务登录在 Unity Android 上无法正常运行