Я использую LiveData для наблюдения за запросом Room, который фильтрует таблицу по логическому значению в таблице. Логическое значение указывает, была ли строка загружена во внешнюю базу данных или нет.
Вот запрос, который я наблюдаю:
memodao.kt
@Query("SELECT * FROM memos WHERE uploaded = 0 ORDER BY id ASC")
fun getUnsyncedMemos(): LiveData<List<Memo>>
//including this statement because it's used later
@Update
suspend fun update(memo: Memo): Int
Когда запускаются LiveData, я беру эту строку, загрузить его во внешнюю базу данных с помощью Retrofit, а затем, когда Retrofit вернется, я помечаю эту строку как загруженную, чтобы исключить ее из вышеприведенного запроса. ожидается.
Проблема в том, что время от времени запрос снова возвращает одну и ту же строку, даже если он НЕ ДОЛЖЕН встречать предложение where.
Фактически он возвращает устаревшую версию строки, это все еще соответствует предложению where.
Это происходит только время от времени. Для меня это похоже на состояние гонки: начало оператора Room @Update вызывает повторное выполнение @Query, а иногда строка не перезаписывается во времени, поэтому @Query возвращает устаревший результат.
Вот остальная часть соответствующего кода.
CloudSyncService.kt
mMemoRepository.getUnsyncedMemos().observeForever{ memoList ->
memoList.forEach { memo ->
if (!memo.uploaded) uploadMemo(memo) //an unnecessary if, I know.
}
}
private fun uploadMemo(memo: Memo) {
mMemoRepository.uploadMemo(memo).observeOnce(this, Observer {
mCloudOK = it != CLOUD_FAILED
})
}
MemoRepository.kt
override fun getUnsyncedMemos() = memoDao.getUnsyncedMemos()
override fun uploadMemo(memo: Memo): LiveData<Int> {
val mutableLiveData = MutableLiveData<Int>()
CoroutineScope(IO).launch{
memoWebService.uploadMemo(memo).enqueue(object : Callback<Memo> {
override fun onResponse(call: Call<Memo>, response: Response<Memo>) {
if (response.isSuccessful) {
memo.uploaded = true
updateMemo(memo)
mutableLiveData.value = CLOUD_OK
}
else {
mutableLiveData.value = CLOUD_UNKNOWN
}
}
override fun onFailure(call: Call<Memo>, t: Throwable) {
mutableLiveData.value = CLOUD_FAILED
mMutableErrorMessage.value = t.message
}
})
}
return mutableLiveData
}
Мне интересно, если это проблема с сопрограммами, выбрасывающими вещи из разума c и создающими гонку? Я переместил вызовы в подпрограммы и из них, чтобы попытаться исправить это, но я все еще получаю проблему.
Я прочитал о проблеме, когда LiveData возвращает устаревшие данные: Комната LiveData запускается дважды с одной устаревшей эмиссией
Я считаю, что мой вопрос отличается, потому что я не добавляю новых наблюдателей, которые получают устаревшие данные при первом увольнении. У меня есть один наблюдатель, который наблюдает навсегда, который иногда получает устаревшие данные после обновления db @.
Большое спасибо!