安卓 | 科特林 | Flow - 无法转换为 kotlinx.coroutines.flow.StateFlow

Mai*_*sad 6 android android-lifecycle android-architecture-components kotlin-coroutines android-jetpack-datastore

我试图让自己熟悉DataStore,所以在我当前的项目中,我尝试使用它。

在我的依赖中。我已经添加 :

    implementation "androidx.datastore:datastore-preferences:1.0.0-alpha06"
Run Code Online (Sandbox Code Playgroud)

然后我创建了这个类来处理数据存储:

class BasicDataStore(context: Context) :
    PrefsDataStore(
        context,
        PREF_FILE_BASIC
    ),
    BasicImpl {
    override val serviceRunning: Flow<Boolean>
        get() = dataStore.data.map { preferences ->
            preferences[SERVICE_RUNNING_KEY] ?: false
        }
    override suspend fun setServiceRunningToStore(serviceRunning: Boolean) {
        dataStore.edit { preferences ->
            preferences[SERVICE_RUNNING_KEY] = serviceRunning
        }
    }
    companion object {
        private const val PREF_FILE_BASIC = "basic_preference"
        private val SERVICE_RUNNING_KEY = booleanPreferencesKey("service_running")
    }
}
@Singleton
interface BasicImpl {
    val serviceRunning: Flow<Boolean>
    suspend fun setServiceRunningToStore(serviceRunning: Boolean)
}
Run Code Online (Sandbox Code Playgroud)

在我的视图模型中,我尝试使用该值,如下所示:

class MainViewModel(application: Application) : AndroidViewModel(application) {
    ...
    private val basicDataStore = BasicDataStore(application)
    val serviceRunning
            : StateFlow<Boolean> get()
            = basicDataStore.serviceRunning as StateFlow<Boolean>
    fun setServiceRunning(serviceRunning: Boolean) {
        viewModelScope.launch(IO) {
            basicDataStore.setServiceRunningToStore(serviceRunning)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但它给了我以下错误:

Caused by: java.lang.ClassCastException: com.mua.roti.data.datastore.BasicDataStore$serviceRunning$$inlined$map$1 cannot be cast to kotlinx.coroutines.flow.StateFlow
        at com.mua.roti.viewmodel.MainViewModel.getServiceRunning(MainViewModel.kt:33)
...
Run Code Online (Sandbox Code Playgroud)

在 xml 中,在 UI 部分:


        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{main.serviceRunning.value.toString()}" />

Run Code Online (Sandbox Code Playgroud)

使用 viewmodel 一切都变得如此酷和简单,易于阅读和实现。现在我对 Flow 感到困惑。谢谢。

Nag*_*obi 19

流的层次结构如下:StateFlow-> SharedFlow->Flow

因此,您无法真正对其进行转换,如果您想将冷流转换为热 StateFlow,则应该使用stateIn()运算符。在你的情况下:

val serviceRunning: StateFlow<Boolean> 
    get() = basicDataStore.serviceRunning.stateIn(viewModelScope, SharingStarted.Lazily, false)
Run Code Online (Sandbox Code Playgroud)

您可以调整SharingStarted状态流的和/或初始值