这是我的用例:
我正在开发一个通过REST API与服务器通信的应用程序,并将收到的数据存储在SQLite数据库中(它将其用作某些类型的缓存)。
当用户打开屏幕时,必须进行以下操作:
这与呈现here的情况非常相似,但存在细微差别。
由于我使用的是SQLBrite,因此DB observable不会终止(因为在那里注册了ContentObserver
,这会在流中推送新数据),所以像concat
,{{1这样的方法等等不会起作用。
目前,我已使用以下方法解决了这个问题:
merge
好像它工作正常,但它看起来并不优雅和“正确”。
您能否建议或指出一个资源,解释处理这种情况的最佳方法是什么?
答案 0 :(得分:6)
如果你改变思维方式,问题的解决方案实际上非常简单和干净。我正在使用完全相同的数据交互(Retrofit + Sqlbrite),这个解决方案非常有效。
您需要做的是使用两个单独的可观察订阅,这些订阅会处理完全不同的过程。
Database
->
View
:此一个用于附加您的View
(Activity
,Fragment
或任何显示您的数据的内容) db中的持久数据。您为创建的View
订阅了ONCE。
dbObservable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(data -> {
displayData(data);
}, throwable -> {
handleError(throwable);
});
API
->
Database
:另一个从api获取数据并将其保留在数据库中。每次要刷新数据库中的数据时,都会订阅它。
apiObservable
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(data -> {
storeDataInDatabase(data);
}, throwable -> {
handleError(throwable);
});
编辑:
你不想改变"这两种观察结果都是一体的,纯粹是出于你的问题所包含的原因。两个可观察者的行为完全不同。
来自Retrofit的observable
就像一个Single
。它完成它需要做的事情,并完成(使用onCompleted
)。
来自Sqlbrite的observable
是一个典型的Observable
,它会在每次特定表更改时发出一些内容。从理论上讲,它应该在未来完成。
Ofc你可以解决这个问题,但它会带你走远,远离那些干净易读的代码。
如果您确实需要公开单个observable
,那么在订阅您的数据库时,您可以隐藏您实际订阅可观察对象的事实
public void fetchRemoteData() {
apiObservable
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(data -> {
persistData(data);
}, throwable -> {
handleError(throwable);
});
}
fetchRemoteData
dbObservable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe(() -> fetchRemoteData())
.subscribe(data -> {
displayData(data);
}, throwable -> {
handleError(throwable);
});
我建议你真的考虑这一切。因为你强迫自己进入你需要一个可观察的位置的事实,可能会严重限制你。我相信这将会迫使你在将来改变你的概念,而不是保护你免受改变本身的影响。