Reputation: 1070
I am trying to understand how work with Realm
and RxJava2
together (for async transactions) and did some sample project with transactions:
private void writeAllUsers() {
Realm.getDefaultInstance().executeTransactionAsync(realm -> realm.copyToRealmOrUpdate(users));
}
private void getAllUsers() {
getUsers().observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(this::successGetUser, this::handleUserError);
}
private Flowable<RealmResults<User>> getUsers() {
return Realm.getDefaultInstance()
.where(User.class)
.findAllAsync()
.asFlowable();
}
But when I call getAllUsers
, I get exception:
java.lang.IllegalStateException: Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created.
What I did wrong in this case?
Upvotes: 0
Views: 1303
Reputation: 81588
RealmResults<T>
represents a thread-local collection of proxy views, where due to Realm's MVCC architecture, they are bound to the current thread-local version of the database.
This means that a managed RealmResults or Realm or RealmObject cannot be passed between threads.
So you cannot and mustn't do this with a RealmResults :
getUsers()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
Passing managed results from io
to main thread
is no-no!
asFlowable
just wraps the RealmChangeListener (only valid on looper threads) as a Flowable, so thread confinement is still a thing.
In fact, it will never terminate, and you should make sure you unsubscribe.
So to hide the results as Flowable in such a way that it works on any thread, assuming you don't do thread jumps with it:
private Flowable<RealmResults<User>> getUsers(Realm realm) {
if(realm.isAutoRefresh()) {
return realm
.where(User.class)
.findAllAsync()
.asFlowable()
.filter(RealmResults::isLoaded);
} else {
return Flowable.just(realm
.where(User.class)
.findAll());
}
}
Reading on background looper thread and passing unmanaged results on change using copyFromRealm()
is slightly trickier, you should not use copyFromRealm()
on a RealmResults on a UI thread.
Upvotes: 1