Лучший способ «обновить» LiveData, предоставляемый базой данных комнат - PullRequest
1 голос
/ 19 октября 2019

В настоящее время я использую Room для хранения списка переводов слов и возвращаю запросы в виде LiveData для отслеживания вставок и обновлений. Однако я сталкиваюсь с проблемами, когда мне нужно повторно получить переводы для другого исходного языка (моя текущая стратегия состоит в том, чтобы переназначить жилые данные в результате запроса помещения).

Я выбираю языки для переводаи переводы для конкретного языка с использованием приведенных ниже SQL-запросов

@Dao
interface TranslationDatabaseDao {
   ...

   //Returns all pairs of languages to translate to/from
   @Query("SELECT * FROM language_pairs")
   fun getAllLanguagePairs(): LiveData<List<LanguagePair>>

   //Returns translations with the specified source language
   @Query("SELECT * FROM translations WHERE sourceLanguage = :language")
   fun getTranslations(language: String): LiveData<List<TranslationResult>>

   ...
}

, которые я вызываю при создании экземпляра модели представления, и снова при смене языка пользователем (см. changeLanguage(...) ниже).

class translationViewmodel(private val database: TranslationDatabaseDao, initLanguage: String): ViewModel() {
   ...

   val languages: LiveData<List<LanguagePair>> = database.getAllLanguagePairs()
   val currentLanguages = Transformations.map(languages) { allLanguages ->
      allLanguages?.let {
         it[0] //Get the first language in the list
      }
   }

   var translations: LiveData<List<TranslationResult>> = database.getTranslations(initLanguage)

   ...

   fun changeLanguage(language: String) {
      coroutinesScope.launch {
         translations = withContext(Dispatchers.IO) {
            database.getTranslations(language)
         }
      }
   }

   ...
}

Повторное назначение списка переводов приводит к тому, что фрагмент, наблюдающий жизненные данные, продолжает наблюдать старые живые данные, поэтому моя стратегия заключалась в том, чтобы удалить наблюдателя и переназначить его во фрагменте при смене языков. Это не кажется лучшим решением здесь, и я также не уверен, как обеспечить загрузку данных перед удалением предыдущего наблюдателя и его повторным созданием (я использую сопрограммы, поэтому мне нужен способ обратного вызовакогда жилатата была возвращена).

Возможные решения

  1. Пусть база данных выдаст только объект List, а не livingata. Я мог бы затем сохранить его в изменяемой среде. Это не идеально, поскольку вставки и обновления не отражаются в возвращаемом списке автоматически, поэтому мне придется повторно выбирать данные каждый раз, когда я изменяю список переводов для определенного языка.
  2. Выбрать всепереводы, а затем фильтровать их каждый раз, когда язык меняется. Это будет немного ресурсоемким, как только список языков увеличится.

Итак, мой вопрос: есть ли лучший способ переназначения liveata после смены языка? Или, скорее, существует ли приемлемый способ, чтобы фрагмент был осведомлен об этом переназначении?

1 Ответ

1 голос
/ 19 октября 2019

Вы можете создать еще один LiveData для языка и использовать switchMap , чтобы сопоставить его с переводами, например:

class translationViewmodel(private val database: TranslationDatabaseDao, initLanguage: String): ViewModel() {
  val language = MutableLiveData<String>("en")
  val translations = language.switchMap { language -> 
    database.getTranslations(language)
  }
  ...
}

Теперь просто измените язык и переводытоже будет обновляться

viewmodel.language.value = "es"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...