即使没有变化也会产生流量值
Flow emitting value even when there are no change
我的 android 应用程序中有一个数据存储区,用于存储我的个人资料详细信息。并检索如下
suspend fun saveUser(user: User) {
dataStore.edit {
it[USER_ID] = user.id
it[USER_NAME] = user.name
it[USER_MOBILE] = user.phone
it[USER_EMAIL] = user.email
it[USER_IMAGE] = user.image
it[USER_ADDRESS] = user.address
}
}
val userDate = dataStore.data
.catch { e ->
if (e is IOException) {
Log.e("PREFERENCE", "Error reading preferences", e)
emit(emptyPreferences())
} else {
throw e
}
}
.map { pref ->
val userId = pref[USER_ID] ?: ""
val userName = pref[USER_NAME] ?: ""
val userEmail = pref[USER_EMAIL] ?: ""
val userImage = pref[USER_IMAGE] ?: ""
val userPhone = pref[USER_MOBILE] ?: ""
val userAddress = pref[USER_ADDRESS] ?: ""
User(
name = userName,
image = userImage,
address = userAddress,
phone = userPhone,
id = userId,
email = userEmail
)
}
与此同时,我正在保存用户的可用性状态
suspend fun saveIsAvailable(boolean: Boolean) {
dataStore.edit {
it[USER_IS_AVAILABLE] = boolean
}
}
我正在我的视图模型中收集这样的用户个人资料详细信息
viewModelScope.launch(Default) {
RiderDataStore.userDate.collect {
user.postValue(it)
}
}
每当我更改用户可用性时,我的用户详细信息流也会被触发,这是不必要的并导致 ui 抖动(图像重新加载)。为什么会发生这种情况以及如何使流程仅在数据具体更改用户详细信息时触发。
这是因为您更新了用户 属性(在 DataStore
中),同时使用 userDate.collect
您正在观察对用户所做的所有更改(在 DataStore
).您当前的代码无法区分用户的“好”和“坏”更新。
由于您似乎忽略了 DataStore
Flow
中称为 userDate
的 可用性 ,因此您返回的 User
对象应该在可用性发生变化后确实保持不变。 Kotlin Flow
的默认行为是在每次更改时发出,即使数据相同。但是您可以通过在 map
运算符之后添加一个 .distinctUntilChanged()
来解决这个问题,例如:
val userDate = dataStore.data
.catch { e ->
if (e is IOException) {
Log.e("PREFERENCE", "Error reading preferences", e)
emit(emptyPreferences())
} else {
throw e
}
}
.map { pref ->
val userId = pref[USER_ID] ?: ""
val userName = pref[USER_NAME] ?: ""
val userEmail = pref[USER_EMAIL] ?: ""
val userImage = pref[USER_IMAGE] ?: ""
val userPhone = pref[USER_MOBILE] ?: ""
val userAddress = pref[USER_ADDRESS] ?: ""
User(
name = userName,
image = userImage,
address = userAddress,
phone = userPhone,
id = userId,
email = userEmail
)
}.distinctUntilChanged()
另见 docs。它确保不会一遍又一遍地发出相同的数据。
我的 android 应用程序中有一个数据存储区,用于存储我的个人资料详细信息。并检索如下
suspend fun saveUser(user: User) {
dataStore.edit {
it[USER_ID] = user.id
it[USER_NAME] = user.name
it[USER_MOBILE] = user.phone
it[USER_EMAIL] = user.email
it[USER_IMAGE] = user.image
it[USER_ADDRESS] = user.address
}
}
val userDate = dataStore.data
.catch { e ->
if (e is IOException) {
Log.e("PREFERENCE", "Error reading preferences", e)
emit(emptyPreferences())
} else {
throw e
}
}
.map { pref ->
val userId = pref[USER_ID] ?: ""
val userName = pref[USER_NAME] ?: ""
val userEmail = pref[USER_EMAIL] ?: ""
val userImage = pref[USER_IMAGE] ?: ""
val userPhone = pref[USER_MOBILE] ?: ""
val userAddress = pref[USER_ADDRESS] ?: ""
User(
name = userName,
image = userImage,
address = userAddress,
phone = userPhone,
id = userId,
email = userEmail
)
}
与此同时,我正在保存用户的可用性状态
suspend fun saveIsAvailable(boolean: Boolean) {
dataStore.edit {
it[USER_IS_AVAILABLE] = boolean
}
}
我正在我的视图模型中收集这样的用户个人资料详细信息
viewModelScope.launch(Default) {
RiderDataStore.userDate.collect {
user.postValue(it)
}
}
每当我更改用户可用性时,我的用户详细信息流也会被触发,这是不必要的并导致 ui 抖动(图像重新加载)。为什么会发生这种情况以及如何使流程仅在数据具体更改用户详细信息时触发。
这是因为您更新了用户 属性(在 DataStore
中),同时使用 userDate.collect
您正在观察对用户所做的所有更改(在 DataStore
).您当前的代码无法区分用户的“好”和“坏”更新。
由于您似乎忽略了 DataStore
Flow
中称为 userDate
的 可用性 ,因此您返回的 User
对象应该在可用性发生变化后确实保持不变。 Kotlin Flow
的默认行为是在每次更改时发出,即使数据相同。但是您可以通过在 map
运算符之后添加一个 .distinctUntilChanged()
来解决这个问题,例如:
val userDate = dataStore.data
.catch { e ->
if (e is IOException) {
Log.e("PREFERENCE", "Error reading preferences", e)
emit(emptyPreferences())
} else {
throw e
}
}
.map { pref ->
val userId = pref[USER_ID] ?: ""
val userName = pref[USER_NAME] ?: ""
val userEmail = pref[USER_EMAIL] ?: ""
val userImage = pref[USER_IMAGE] ?: ""
val userPhone = pref[USER_MOBILE] ?: ""
val userAddress = pref[USER_ADDRESS] ?: ""
User(
name = userName,
image = userImage,
address = userAddress,
phone = userPhone,
id = userId,
email = userEmail
)
}.distinctUntilChanged()
另见 docs。它确保不会一遍又一遍地发出相同的数据。