#android #kotlin-coroutines #flow #android-jetpack-datastore
Вопрос:
У меня есть хранилище данных в моем приложении для 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)
}
}
Всякий раз, когда я изменяю доступность пользователя, мой поток сведений о пользователе также запускается, что является ненужным и вызывает дрожание пользовательского интерфейса (перезагрузка изображения). Почему это происходит и как включить запуск потока только в том случае, если данные изменяются конкретно в отношении сведений о пользователе.
Ответ №1:
Это происходит потому, что вы обновляете свойство пользователя (in DataStore
) и в то же время userDate.collect
наблюдаете за всеми изменениями, внесенными в пользователя (in DataStore
). В вашем текущем коде нет возможности отличить «хорошие» и «плохие» обновления пользователя.
Поскольку вы , похоже, игнорируете доступность в DataStore
Flow
вызываемых userDate
вами объектах, возвращаемые User
объекты действительно должны оставаться идентичными после изменения доступности. Поведение по умолчанию для Kotlin Flow
заключается в выделении при каждом изменении, даже если данные идентичны. Но вы можете исправить это, просто добавив .distinctUntilChanged()
после map
оператора, например:
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()
См.также документы. Это гарантирует, что идентичные данные не будут передаваться снова и снова.