我正在从Realm读取/写入这个异常
06-19 09:49:26.352 11404-11404 / ****** E / ContentValues:loadData:OnError Realm从错误的线程访问 . Realm对象只能在创建它们的线程上访问 . java.lang.IllegalStateException:从错误的线程访问Realm . Realm对象只能在创建它们的线程上访问 . at io.realm.BaseRealm.checkIfValid(BaseRealm.java:385)at io.realm.RealmResults.isLoaded(RealmResults.java:115)at io.realm.OrderedRealmCollectionImpl.size(OrderedRealmCollectionImpl.java:307)at io.realm . RealmResults.size(RealmResults.java:60)at java.util.AbstractCollection.isEmpty(AbstractCollection.java:86)at / ****** .lambda $ loadData $ 0(SplashPresenter.java:42)at / *** *** $ Lambda $ 1.test(未知来源)at io.reactivex.internal.operators.observable.ObservableFilter $ FilterObserver.onNext(ObservableFilter.java:45)at io.reactivex.observers.SerializedObserver.onNext(SerializedObserver.java) :111)ato.reactivex.internal.operators.observable.ObservableDelay $ DelayObserver $ 1.run(ObservableDelay.java:84)at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:59)at io.reactivex .internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:51)at java.util.concurrent.FutureTask.run(FutureTask.java:237)at java.util.concurrent.ScheduledThreadPoolExecutor $ Schedul edFutureTask.run(ScheduledThreadPoolExecutor.java:272)java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:607)at java.lang .Thread.run(Thread.java:761)
这是代码:
mSubscribe = Observable.just(readData())
.delay(DELAY, TimeUnit.SECONDS)
.filter(value -> !value.isEmpty())
.switchIfEmpty(createRequest())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()).subscribe(data -> {
getView().hideLoading();
writeData(data);
},
(throwable -> {
}));
Read data
private List<CategoryModel> readData() {
Realm defaultInstance = Realm.getDefaultInstance();
List<CategoryModel> title = defaultInstance.where(CategoryModel.class).findAllSorted("title");
defaultInstance.close();
return title;
}
Write data
private void writeData(List<CategoryModel> categoryModels) {
try {
Realm defaultInstance = Realm.getDefaultInstance();
defaultInstance.executeTransactionAsync(realm -> realm.insertOrUpdate(categoryModels));
defaultInstance.close();
} finally {
getView().notifyActivity(categoryModels);
}
}
如何使用正确的线程遵循此逻辑?
4 回答
您只能在事务中操作Realm对象,或者只能在读/写这些对象的线程中操作 . 在您的情况下,您从readData方法获取RealmResult并使用RxJava切换导致异常的线程 . 使用copyFromRealm从realm获取数据,它将它们作为普通对象而不是realm对象返回 .
The only rule to using Realm across threads is to remember that Realm, RealmObject or RealmResults instances cannot be passed across threads .
如果要从不同的线程访问相同的数据,只需获取 a new Realm instance (即
Realm.getDefaultInstance()
)并通过查询获取对象(然后在线程末尾关闭Realm) .对象将映射到磁盘上的相同数据,并且可以从任何线程读取和写入!您也可以使用
realm.executeTransactionAsync()
(如this)在后台线程上运行代码 .通过不尝试在
Schedulers.io()
上读取您的UI线程(Realm提供自动更新延迟加载的代理视图,毕竟为UI线程上的数据提供更改通知) .所以不要这样
你应该有类似的东西
这样(如果我没有弄乱任何东西),你最终会得到here和here所描述的被动数据层,除非没有映射出整个结果的额外开销 .
EDIT:
从Realm 4.0开始,可以直接将RealmResults公开为Flowable(在UI线程或后台循环线程上) .
您需要从领域对象中提取所需的数据到POJO并使用map运算符发出POJO,以便使用Android主线程上的pojo从视图对象中更新 .