Android |科特林 |流 - 无法转换为 kotlinx.coroutines.flow.StateFlow
Android | Kotlin | Flow - cannot be cast to kotlinx.coroutines.flow.StateFlow
-
android
-
android-lifecycle
-
android-architecture-components
-
kotlin-coroutines
-
android-jetpack-datastore
我正在努力让自己熟悉 DataStore
,所以在我当前的项目中,我正在尝试使用它。
在我的依赖中。我已经添加了:
implementation "androidx.datastore:datastore-preferences:1.0.0-alpha06"
然后我创建了这个 class 来处理数据存储:
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)
}
在我的视图模型中,我尝试使用该值,如下所示:
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)
}
}
}
但它给了我以下错误:
Caused by: java.lang.ClassCastException: com.mua.roti.data.datastore.BasicDataStore$serviceRunning$$inlined$map cannot be cast to kotlinx.coroutines.flow.StateFlow
at com.mua.roti.viewmodel.MainViewModel.getServiceRunning(MainViewModel.kt:33)
...
在xml中,在UI部分:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{main.serviceRunning.value.toString()}" />
有了 viewmodel,一切都变得如此酷和简单,易于阅读和实施。现在我对 Flow 感到困惑。谢谢。
流的层次结构如下:StateFlow
-> SharedFlow
-> Flow
所以您不能真正转换它,如果您想将冷流转换为热 StateFlow,则应该使用 stateIn() 运算符。
在你的情况下:
val serviceRunning: StateFlow<Boolean>
get() = basicDataStore.serviceRunning.stateIn(viewModelScope, SharingStarted.Lazily, false)
您可以调整状态流的 SharingStarted
and/or 初始值
android
android-lifecycle
android-architecture-components
kotlin-coroutines
android-jetpack-datastore
我正在努力让自己熟悉 DataStore
,所以在我当前的项目中,我正在尝试使用它。
在我的依赖中。我已经添加了:
implementation "androidx.datastore:datastore-preferences:1.0.0-alpha06"
然后我创建了这个 class 来处理数据存储:
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)
}
在我的视图模型中,我尝试使用该值,如下所示:
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)
}
}
}
但它给了我以下错误:
Caused by: java.lang.ClassCastException: com.mua.roti.data.datastore.BasicDataStore$serviceRunning$$inlined$map cannot be cast to kotlinx.coroutines.flow.StateFlow
at com.mua.roti.viewmodel.MainViewModel.getServiceRunning(MainViewModel.kt:33)
...
在xml中,在UI部分:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{main.serviceRunning.value.toString()}" />
有了 viewmodel,一切都变得如此酷和简单,易于阅读和实施。现在我对 Flow 感到困惑。谢谢。
流的层次结构如下:StateFlow
-> SharedFlow
-> Flow
所以您不能真正转换它,如果您想将冷流转换为热 StateFlow,则应该使用 stateIn() 运算符。 在你的情况下:
val serviceRunning: StateFlow<Boolean>
get() = basicDataStore.serviceRunning.stateIn(viewModelScope, SharingStarted.Lazily, false)
您可以调整状态流的 SharingStarted
and/or 初始值