【发布时间】:2017-11-18 15:20:38
【问题描述】:
我有一个示例 API 请求,它返回用户关注列表的列表。我想在用户加载监视列表屏幕时实现以下流程:
立即从数据库缓存中加载数据。(
cacheWatchList)-
在后台发起 RetroFit 网络调用。
我。
onSuccess返回apiWatchList
ii.onError返回cacheWatchList -
区分
cacheWatchList与apiWatchList我。相同 -> 一切都很好,因为数据已经显示给用户什么都不做。
二。不同 -> 将
apiWatchList保存到本地存储并将apiWatchList发送到下游。
到目前为止我做了什么?
Watchlist.kt
data class Watchlist(
val items: List<Repository> = emptyList()
)
LocalStore.kt(Android 房间)
fun saveUserWatchlist(repositories: List<Repository>): Completable {
return Completable.fromCallable {
watchlistDao.saveAllUserWatchlist(*repositories.toTypedArray())
}
}
RemoteStore.kt(改造 api 调用)
fun getWatchlist(userId: UUID): Single<Watchlist?> {
return api.getWatchlist(userId)
}
DataManager.kt
fun getWatchlist(userId: UUID): Flowable<List<Repository>?> {
val localSource: Single<List<Repository>?> =
localStore.getUserWatchlist()
.subscribeOn(scheduler.computation)
val remoteSource: Single<List<Repository>> = remoteStore.getWatchlist(userId)
.map(Watchlist::items)
.doOnSuccess { items: List<Repository> ->
localStore.saveUserWatchlist(items)
.subscribeOn(scheduler.io)
.subscribe()
}
.onErrorResumeNext { throwable ->
if (throwable is IOException) {
return@onErrorResumeNext localStore.getUserWatchlist()
}
return@onErrorResumeNext Single.error(throwable)
}
.subscribeOn(scheduler.io)
return Single.concat(localSource, remoteSource)
}
上述流程的问题是,即使两个数据相同,它也会为下游(演示者)的每个流源调用onNext 两次。
我可以在演示者中执行数据差异逻辑并进行相应更新,但我希望DataManager 类为我处理逻辑(CleanArchitecture,SOC)。
我的问题?
实现上述逻辑的最佳方法是什么?
我是否泄露了 DataManager 中的内部订阅(参见:
doOnSuccess代码)?当演示者被销毁时,我正在处理外部订阅。
【问题讨论】:
-
试过google的paging库?
-
@pskink 通过将默认适配器扩展到
PagedListAdapter,我们可以解决这个问题。但是再次PagedListAdapter导致表示层发生变化,我希望数据层来处理数据变化。 -
什么意思?你不能 invalidate() 你的
DataSource吗? -
@pskink 太简短了,我不想在表示(UI)层写一些逻辑,改变适配器实现或写 DiffUtils 回调机制。我想让演示者尽可能地愚蠢,希望数据层负责在正确的时间发送正确的数据。
-
您的演示者只需创建
LivePagedListProvider以及您将在自定义DataSource中实现的所有逻辑
标签: android retrofit2 rx-java2 android-room