Access to the rule from the wrong stream Exception when sending a copy using copyFromRealm

When streaming copying realm objects instead of referencing realm and observing it in the Schedulers.IO stream, a crash occurs with the well-known exception message "Realm access from wrong thread". Realm objects can only be accessed in the stream they were created. "

Shouldn't a copy be streaming? Can I produce it from one thread and process it in another thread?

This is how I create the observable.

public Observable<Brand> getAllBrands() { return realm.where(Brand.class) .findAll() .asObservable() .flatMap(Observable::from) .map(brand -> realm.copyFromRealm(brand)); } 

This is how I observe 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(); } }); 
+5
source share
2 answers

You subscribe to schedulers.io when using a Realm instance from a user interface thread:

 realm.where(Brand.class) .findAll() .asObservable() .flatMap(Observable::from) .map(brand -> realm.copyFromRealm(brand)) // realm instance on the wrong thread .subscribeOn(schedulers.io()); 

What you need is an easy way to move the request across threads, which is still under development: https://github.com/realm/realm-java/pull/1978 , Until then, you can work around this by doing so :

 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); } 

Note that Charmisteners Realm only work on Looper streams, which means that you probably need to change the workflow to H

 HandlerThread bgThread = new HandlerThread("workerThread"); Handler handler = new Handler(bgThread.getLooper()); getAllBrands(realm).subscribeOn(HandlerScheduler.from(handler)); 
+7
source

Question

Is it possible to create it from one thread and process it in another thread?

The answer is NO. You can read the description of the kingdom in here.

Although Realm files can be accessed simultaneously by multiple threads, you cannot transfer Realms, Realm objects, queries, and results between threads. The sample thread shows how to use Realm in a multi-threaded environment.

0
source

Source: https://habr.com/ru/post/1244550/


All Articles