使用RxJava concat运算符时遇到问题。我有两个observable,第一个从服务器数据库发出结果,另一个从本地数据库发出结果,然后我结束:
// Uses a Realm in the UI thread
Observable<MyResult> remoteObservable = mRemoteDataSource.find(tId);
// Uses Retrofit
Observable<MyResult> localObservable = mLocalDataSource.find(tId);
Observable.concat(localObservable, remoteObservable)
.doOnNext(result -> /* Do my stuff */)
.observeOn(AndroidSchedulers.mainThread())
.doOnError(throwable -> throwable.printStackTrace())
.subscribe()
所以这会导致我的问题,因为我没有使用subscribeOn()
连接的observable正在AndroidScheduler.MainThread()
上运行,这不会运行远程并启动NetworkOnMainThreadException
。
如果我实现subscribeOn(Schedulers.computation())
我得到Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created
,因为当然Observable没有在Realm实例存在的线程上运行。
我已经搜索了其他问题并且我没有得到任何有用的东西,我已经检查了领域做出的例子:https://github.com/realm/realm-java/blob/master/examples/rxJavaExample/src/main/java/io/realm/examples/rxjava/retrofit/RetrofitExample.java但奇怪的是我看到改装的observable没有任何订阅而且它有效。
为什么它对样本起作用,在我的代码中我不能这样做?有什么建议吗?
答案 0 :(得分:2)
我相信你应该在正确的地方使用subscribeOn()
。
// Uses a Realm in the UI thread
Observable<MyResult> realmObservable = mRealmDataSource.find(tId).subscribeOn(AndroidSchedulers.mainThread());
// Uses Retrofit
Observable<MyResult> retrofitObservable = mRetrofitDataSource.find(tId).subscribeOn(Subscribers.io());
Observable.concat(realmObservable, retrofitObservable)
.doOnNext(result -> /* Do my stuff */)
.subscribeOn(AndroidSchedulers.mainThread())
.observeOn(AndroidSchedulers.mainThread())
.doOnError(throwable -> throwable.printStackTrace())
.subscribe()
看看它是否解决了您的问题。
答案 1 :(得分:2)
您可以连接本地和远程可观察对象,如下所示:
// Uses a Realm in the UI thread
Observable<MyResult> remoteObservable = mRemoteDataSource.find(tId);
// Uses Retrofit
Observable<MyResult> localObservable = mLocalDataSource.find(tId);
Observable.concat(localObservable, remoteObservable).first()
.map(new Func1<MyResult, MyResult>() {
@Override
public myResult call(MyResult result) {
if (result == null) {
throw new IllegalArgumentException();
}
return result;
}
});
订阅如下:
CompositeSubscription mCompositeSubscription = new CompositeSubscription();
final Subscription subscription = mRepo.find(tId
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<MyResult>() {
@Override
public void onCompleted() {
// Completed
}
@Override
public void onError(Throwable e) {
// onError
}
@Override
public void onNext(MyResult result) {
//onSuccess
}
});
mCompositeSubscription.add(subscription);
您可以查看此仓库以获取RxJava + Retrofit + Realm https://github.com/savepopulation/wikilight
祝你好运!答案 2 :(得分:0)
不是在subscribeOn
使用mRealmDataSource.find(tId).subscribeOn(AndroidSchedulers.mainThread())
就像说的那样:https://stackoverflow.com/a/39304891/2425851
您可以使用Observable.defer
例如:
class RealmDataSource{
fun find(id: String): Observable<MyResult> {
// Default pattern for loading data on a background thread
return Observable.defer{
val realm = Realm.getInstance()
val query = realm
.where(MyResult::class.java)
val flowable =
if (realm.isAutoRefresh) {
query
.findAllAsync()
.asFlowable()
.filter(RealmResults::isLoaded)
} else {
Flowable.just(query.findAll())
}
return@defer flowable
.toObservable()
}
}
然后将不使用subscribeOn
// Uses a Realm
Observable<MyResult> realmObservable = mRealmDataSource.find(tId);
// Uses Retrofit
Observable<MyResult> remoteObservable = mRemoteDataSource.find(tId);
有关更多信息,请参见https://realm.io/blog/realm-java-0-87-0/