首页 > 解决方案 > 如果没有连接,如何从本地获取我的应用程序,如果有,如何从远程获取?

问题描述

MyMainRepository是从 API 获取数据并插入数据库,然后显示在 UI 上的。

override fun fetchAll() {
    Observable.fromCallable { local.fetchPosts() }
        .doOnNext {
            remote.fetchPosts().concatMap { posts ->
                local.insert(*posts.toTypedArray())
                Observable.just(posts)
            }
        }
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(
            { outcome.success(it) },
            { error: Throwable -> outcome.failed(error) }
        ).addTo(compositeDisposable)
}

outcome变量是 aPublishObject类型,Response即,或。LoadingSuccessFailure

override val outcome = PublishSubject.create<Response<List<Post>>>()

[...]

sealed class Response<T> {
    companion object {
        fun <T> loading(loading: Boolean): Response<T> = Progress(loading)
        fun <T> success(data: T): Response<T> = Success(data)
        fun <T> failure(e: Throwable): Response<T> = Failure(e)
    }

    data class Progress<T>(var loading: Boolean) : Response<T>()
    data class Success<T>(var data: T) : Response<T>()
    data class Failure<T>(var e: Throwable) : Response<T>()
}

它执行一个方法local.fetchPosts(),该方法是负责访问 DAO 函数的函数。

fun fetchPosts() = database.postDao().fetchAll()

[...]

@Query("SELECT * FROM posts ORDER BY createdAt DESC")
fun fetchAll(): List<Post>

是的addTo扩展Disposable

fun Disposable.addTo(compositeDisposable: CompositeDisposable) {
    compositeDisposable.add(this)
}

我已经尝试concatMap在 之后立即使用Observable.fromCallable,但它会直接显示来自 API 的数据,同时doOnNext会从数据库中显示,但不会更新列表,从而删除已从远程服务器中删除的内容。

标签: androidrx-java2android-roomandroid-architecture-components

解决方案


首先,您必须了解这doOnNext是一个副作用运算符,以及它的家族,副作用运算符仅预测执行次要操作(例如记录)的排放,无论如何它们不会影响流。

所以,你正在做可观察的

remote.fetchPosts().concatMap { posts ->
            local.insert(*posts.toTypedArray())
            Observable.just(posts)
        }

永远不会工作,因为它没有被订阅。现在您必须根据您想要的行为做出决定,我假设您的用例是:

  • 尝试从 API 获取数据。

  • 如果成功缓存它,如果不查询DAO

  • 显示它

然后这样的事情会起作用:

remote.fetchPosts()
    // cache the data from remote.
    .doOnNext(posts -> local.insert(*posts.toTypedArray()))
    // if an error happens, use the posts in the DAO.
    .onErrorResumeNext { Observable.fromCallable { local.fetchPosts() } }
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    [...]

推荐阅读