当流式传输领域对象而不是领域引用的副本并在线程上观察它时 Schedulers.IO 会出现崩溃,并显示著名的异常消息"来自不正确线程的领域访问。Realm 对象只能在创建它们的线程中访问。
副本不应该是无线程的吗?我可以从一个线程生成它并在另一个线程上处理它吗?
这就是我创建可观察性的方式。
public Observable<Brand> getAllBrands() {
return realm.where(Brand.class)
.findAll()
.asObservable()
.flatMap(Observable::from)
.map(brand -> realm.copyFromRealm(brand));
}
以下是我观察getAllBrands()的方式。
Observable<Brand> brandObservable = dataManager.getAllBrands();
brandObservable.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Observer<Brand>() {
@Override
public void onCompleted() {
Log.d("reactive", "completed");
}
@Override
public void onError(Throwable e) {
Log.d("reactive", e.getMessage());
}
@Override
public void onNext(Brand brand) {
dataSource.add(brand.getName());
myAdapter.notifyDataSetChanged();
}
});
您在使用 Realm 实例时从 UI 线程订阅schedulers.io
:
realm.where(Brand.class)
.findAll()
.asObservable()
.flatMap(Observable::from)
.map(brand -> realm.copyFromRealm(brand)) // realm instance on the wrong thread
.subscribeOn(schedulers.io());
你追求的是一种跨线程移动查询的简单方法,这仍然在这里进行中:https://github.com/realm/realm-java/pull/1978。在此之前,您可以通过像这样自己执行此操作来解决它:
public Observable<Brand> getAllBrands(final Realm realm) {
return Observable.create(new Observable.OnSubscribe<List<Brand>>() {
@Override
public void call(final Subscriber<? super List<Brand>> subscriber) {
Realm obsRealm = Realm.getInstance(realm.getConfiguration());
final RealmResults<Brand> results = obsRealm.where(Brand.class).findAll();
final RealmChangeListener listener = new RealmChangeListener() {
@Override
public void onChange() {
subscriber.onNext(realm.copyFromRealm(results));
}
};
results.addChangeListener(listener);
subscriber.add(Subscriptions.create(new Action0() {
@Override
public void call() {
realm.removeChangeListener(listener);
realm.close();
}
}));
}
})
.flatMap(Observable::from);
}
请注意,Realm Change监听器只在 Looper 线程上运行,这意味着您可能需要将工作线程更改为 H
HandlerThread bgThread = new HandlerThread("workerThread");
Handler handler = new Handler(bgThread.getLooper());
getAllBrands(realm).subscribeOn(HandlerScheduler.from(handler));
问题
我可以从一个线程生成它并在另一个线程上处理它吗?
答案是否定的。你可以在这里阅读领域描述
虽然 Realm 文件可以由多个线程同时访问,但你不能在线程之间交接 Realm、Realm 对象、查询和结果。线程示例展示了如何在多线程环境中使用 Realm。