如果没有连接,如何让我的应用程序从本地获取,如果有连接,如何从远程获取?
How do I make my app fetch from local if there is no connectivity and from remote if there is?
我的MainRepository
是从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
变量是 Response
类型的 PublishObject
,即 Loading
、Success
或 Failure
。
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)
}
我试过在 Observable.fromCallable
之后使用 concatMap
,但它会直接显示来自 API 的数据,而 doOnNext
会显示来自数据库,但它不会更新列表,删除已从远程服务器删除的内容。
首先你必须明白 doOnNext
是一个 Side Effect Operator,连同它的家族,副作用运算符只预期执行次要操作(例如日志记录)的排放,他们不'无论如何都会影响流。
因此,您正在做可观察的事情
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())
[...]
我的MainRepository
是从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
变量是 Response
类型的 PublishObject
,即 Loading
、Success
或 Failure
。
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)
}
我试过在 Observable.fromCallable
之后使用 concatMap
,但它会直接显示来自 API 的数据,而 doOnNext
会显示来自数据库,但它不会更新列表,删除已从远程服务器删除的内容。
首先你必须明白 doOnNext
是一个 Side Effect Operator,连同它的家族,副作用运算符只预期执行次要操作(例如日志记录)的排放,他们不'无论如何都会影响流。
因此,您正在做可观察的事情
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())
[...]