Room – это основной источник данных, а Firebase – вторичный источник данных, который должен синхронизировать данные между устройствами и платформами.
Я уже реализовал все необходимые операции как из Room, так и из Firebase: получить, добавить, обновить, удалить. Все работает отлично.
Теперь мне нужно определить правила и логику синхронизации данных между Room и Firebase, когда пользователь входит в систему.
Когда приложение запускается, я изменил функцию getNotes() следующим образом:
Код: Выделить всё
override fun getNotes(): Flow {
return dao.getNotes()
}
Код: Выделить всё
override fun getNotes(): Flow {
return flowOf(dao.getNotes(), getRemoteNotes()).flattenMerge().combine(
dao.getNotes()
) { remoteNotes, localNotes ->
mergeNotes(remoteNotes, localNotes)
}.flatMapLatest {
it
}
}
Код: Выделить всё
private fun getRemoteNotes(): Flow = flow {
try {
val uid = authenticationManager.getUId()
val querySnapshot = remoteGeneralCollection
.document("${uid}")
.collection(Constants.FIRESTORE_USER_BACKUP_COLLECTION)
.get()
.await()
val notesRemoteList = querySnapshot.documents.map {
val noteId = it["id"] as Long
val noteTitle = it["title"] as String
val noteContent = it["content"] as String
val noteTimestamp = it["timestamp"] as Long
Note(
title = noteTitle,
content = noteContent,
timestamp = noteTimestamp,
id = noteId.toInt()
)
}
emit(notesRemoteList)
} catch (e: Exception) {
e.printStackTrace()
}
}
Код: Выделить всё
private fun mergeNotes(remoteNotes: List, localNotes: List): Flow = flow {
val localNotesMap = localNotes.associateBy { it.id }
val remoteNotesMap = remoteNotes.associateBy { it.id }
val mergedNotes = remoteNotes.map { remoteNote ->
val localNote = localNotesMap[remoteNote.id]
if (localNote != null) {
val mostRecentNote = if (remoteNote.timestamp > localNote.timestamp) remoteNote else localNote
if (mostRecentNote == remoteNote) {
updateLocalNote(mostRecentNote)
}
mostRecentNote
} else {
insertNote(remoteNote)
remoteNote
}
}
emit(mergedNotes)
}
Я не уверен, что управление потоками в функции getNotes корректно, но другого решения для объединения двух потоков из локального и удаленного я не нашел.
Мне хотелось бы понять, почему эта реализация вызывает бесконечный цикл вызовов mergeNotes. Я также пробовал использовать .distinctUntilChanged() в различных точках коллекций потоков, но это не помогло.
Подробнее здесь: https://stackoverflow.com/questions/775 ... inite-loop