Как реализовать полный репозиторий с помощью kotlin flow

Я пытаюсь реализовать полный репозиторий, используя новую поддержку потока в комнате и поддержку сопрограмм дооснащения. У меня возникают проблемы, решения которых я не могу найти.

Итак, сначала давайте расскажем, чего я добился. Это мой класс ViewModel:

class InvViewModel : ViewModel() {
val repo = Repository()

val flow = flow {
    emit(Lce.Loading())
    val result = repo.updateInv()
    repo.getInv().collect { inv ->
        result?.let { exception ->
            emit(Lce.Error<List<Inv>>(inv, exception))
        } ?: emit(Lce.Content(inv))
    }
}

fun getLocalInv() = flow.asLiveData()

fun updateInv() =
    viewModelScope.launch {
        repo.updateInv()
    }
}

В этом классе я создаю поток, который устанавливает состояние загрузки, запрашивает удаленные данные из сети, когда он получает результат, он подписывается на базу данных комнат и преобразует поток, автоматически возвращаемый из БД, в поток, который знает состояние сетевой вызов, а также данные из базы данных.

Что в этом не так и что я не могу исправить, это следующие две проблемы:

1) Структурируя свой код таким образом, я должен дождаться ответа сети, прежде чем отправлять какие-либо данные. Я бы хотел вернуть поток из базы данных комнаты и показать старые данные, запустить обновление сети и обновить пользовательский интерфейс свежими данными. Но мне нужно было структурировать свой код таким образом, потому что это единственный способ, о котором я мог думать, который мог бы сообщить пользовательскому интерфейсу, не удалось ли сетевой вызов или нет.

2) Технически этот код может работать только при первом выполнении и в случае сбоя сетевого вызова. Если бы я хотел вручную запустить обновление, я бы не смог, потому что поток запускается только тогда, когда он впервые собирается (первое выполнение) или когда база данных комнаты испускает изменение (поэтому, если сеть не выходит из строя, и я сохраняю результат в дб).

Если вам это нужно, код репо такой:

val database = Database.getDb()
val remote = RemoteDataSource()
fun getInv(): Flow<List<Inv>> = database.invDao().getInv()

suspend fun updateInv(): Exception? {
    return try {
        val inv = remote.getInv()
        database.invDao().saveInvs(inv)
        null
    } catch (e: Exception) {
        e.printStackTrace()
        e
    }
}

Где remote.getInv() - это просто модифицированная сопрограмма приостановки, а database.invDao () - это:

@Dao
interface InvDao {
    @Query("SELECT * FROM Inv")
    fun getInv(): Flow<List<Inv>>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun saveInv(inv: Inv)

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun saveInvs(invs: List<Inv>)
}

Мне не нужно иметь все данные в одном потоке, если это не рекомендуется, мне просто нужно знать, как правильно реализовать хороший репозиторий, используя комнату с потоком и модифицируя сопрограмму, и имея db как единственный источник истины.


person alessandro gaboardi    schedule 02.02.2020    source источник
comment
Привет, Эммануэль, это я все еще задаю этот вопрос, но, поскольку я не написал его правильно и не знаю, как я должен себя вести, правильно ли удаление или редактирование старого ответа или нет, я решил опубликовать новый лучше написано. Но нет, этот пост на самом деле не ответил на мой вопрос, потому что я не смогу запустить обновление вручную, например, с помощью swiperefreshlayout, и потому что я был неправ и мне не нужен поток из сети, а сопрограмма, поэтому Не могу совместить 2 потока   -  person alessandro gaboardi    schedule 02.02.2020
comment
Я верю, что ответ, который я дал вам, указывает вам правильное направление, вам просто нужно потратить некоторое время, чтобы связать все это воедино. Существует множество примеров Rx с шаблонами, которые можно легко преобразовать в потоки и сопрограммы, чтобы делать то, что вы хотите.   -  person Emmanuel    schedule 03.02.2020
comment
Вы можете попробовать библиотеку store, которая представляет собой библиотеку для создания репозитория с использованием потока (идеально сочетается с модернизацией и комната)   -  person xiaomi    schedule 16.02.2020