Как сделать вызов асинхронным rxJava

У меня сейчас стоит задача получить список данных из интернета, через retrofit. И если код ответа не успешный(200), то взять этот список данных из бд(room). Как мне сделать это правильно с rxJava? Я использую паттерн mvvm, и проверку я делаю в методе модели, этот метод потом вызывает viewmodel.

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

Сейчас код модели выглядит так:

fun getPeviewCards(): Observable<List<BasePokeModel>> {
        var pokeList: List<BasePokeModel> = listOf()
        apiService.getAllCards()
//            .observeOn(AndroidSchedulers.mainThread())
//            .subscribeOn(Schedulers.io())
            .map {
                pokesList = BasePokeModel.cast(it.body()!!.poke) { pokeInfo ->
                    BasePokeModel(poke.name, poke.images.small)
                }
            }
            .onErrorReturn {
                pokeDao.getAll().map {
                    pokesList = BasePokeModel.cast(it) { pokeInfo ->
                        BasePokeModel(pokeInfo.name, pokeInfo.images.small)
                    }
                }
            }
        }

Понятное дело этот код не работает как надо, он возвращает пустой лист, т.к это многопоток а не асинхронность. В итоге как я понимаю мне нужна асинхронность, как её добиться с rx? Retrofit и Room возвращают Single<>

Переделанное в цепочку

 model.getPreviewRetrofitPokes()
            .subscribeOn(Schedulers.io())
            .subscribe({ onNext ->
                model.refreshTable(onNext.pokes)
                if (onNext.pokes.size != pokesLiveData.value?.size) {
                    val pokesList = BasePokeModel.cast(onNext.pokes) { pokeInfo ->
                        BasePokeModel(pokeInfo.name, pokeInfo.images.small)
                    }
                    pokesLiveData.postValue(pokesList)
                }
            }, {
                model.getPreviewRoomCards()
                    .subscribe({ dbPokes ->
                        var pokeList = listOf<BasePokeModel>()
                        if (dbPokes.isNotEmpty())
                            pokeList = BasePokeModel.cast(dbPoke) { pokeInfo ->
                                BasePokeModel(pokeInfo.name, pokeInfo.images.small)
                            }
                        pokeLiveData.postValue(pokeList)
                    },
                        {
                            Log.d("ErrorDb", it.stackTraceToString())
                        })
            }
            )

Ответы (1 шт):

Автор решения: ЮрийСПб

Должно примерно так выглядеть из presenter/viewModel

model.getDataFromApi()
    .subscribeOn(Schedulers.io())
    .map { /* тут конвертация модели с сервера в общую модель */ }
    .onErrorResumeNext(
         model.getDataFromDb()
           .map { /* тут конвертация модели с БД в общую модель */ }
    )
    .subscribe(
         {
             /*список общих моделек тут*/
             pokeLiveData.postValue(it)
         },
         { /*какая-то непредвиденная ошибка тут*/ }
    )
→ Ссылка