java - RxJava Multithreading with Realm - Realm access from incorrect thread -
background
i using realm within app. when data loaded undergoes intense processing therefore processing occurs on background thread.
the coding pattern in use unit of work pattern , realm exists within repository under datamanager. idea here each repository can have different database/file storage solution.
what have tried
below example of similar code have in foorespository class.
the idea here instance of realm obtained, used query realm objects of interest, return them , close realm instance. note synchronous , @ end copies objects realm unmanaged state.
public observable<list<foo>> getfoosbyid(list<string> fooids) { realm realm = realm.getinstance(foorealmconfiguration); realmquery<foo> findfoosbyidquery = realm.where(foo.class); for(string id : fooids) { findfoosbyidquery.equalto(foo.foo_id_field_name, id); findfoosbyidquery.or(); } return findfoosbyidquery .findall() .asobservable() .doonunsubscribe(realm::close) .filter(realmresults::isloaded) .flatmap(foos -> observable.just(new arraylist<>(realm.copyfromrealm(foos)))); }
this code later used in conjunction heavy processing code via rxjava:
datamanager.getfoosbyid(foo) .flatmap(this::processthefoosinalongrunningprocess) .subscribeon(schedulers.io()) //could schedulers.computation() etc .subscribe(tilechannelsubscriber);
after reading docs, belief above should work, not asynchronous , therefore not need looper thread. obtain instance of realm within same thread therefore not being passed between threads , neither objects.
the problem
when above executed get
realm access incorrect thread. realm objects can accessed on thread created.
this doesn't seem right. thing can think of pool of realm instances getting me existing instance created process using main thread.
kay so
return findfoosbyidquery .findall() .asobservable()
this happens on ui thread, because that's you're calling initially
.subscribeon(schedulers.io())
aaaaand you're tinkering them on schedulers.io()
.
nope, that's not same thread!
as dislike approach of copying zero-copy database, current approach riddled issues due misuse of realmresults.asobservable()
, here's spoiler code should be:
public observable<list<foo>> getfoosbyid(list<string> fooids) { return observable.defer(() -> { try(realm realm = realm.getinstance(foorealmconfiguration)) { //try-finally works realmquery<foo> findfoosbyidquery = realm.where(foo.class); for(string id : fooids) { findfoosbyidquery.equalto(foofields.id, id); findfoosbyidquery.or(); // please guarantee works? } realmresults<foo> results = findfoosbyidquery.findall(); return observable.just(realm.copyfromrealm(results)); } }).subscribeon(schedulers.io()); }
Comments
Post a Comment