How to query Realm on background Thread using RxJava2

Viewed 990

I want to read/query and transform Realm data on a background thread using RxJava2. Here is an Observable:

fun getAllPlayers(): Observable<List<Player>> {
    return Observable.create { emitter ->
        val realm = Realm.getDefaultInstance()
        val players = realm.where(Player::class.java).findAll()

        val listener = RealmChangeListener<RealmResults<Player>> { players ->
            if (!emitter.isDisposed) {
                emitter.onNext(realm.copyFromRealm(players))
            }
        }

        emitter.setDisposable(Disposables.fromRunnable(Runnable {
            players.removeChangeListener(listener)
            realm.close()
        }))

        players.addChangeListener(listener)
        emitter.onNext(realm.copyFromRealm(players))
    }
}

If I try to apply the following to the observable:

getAllPlayers()
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())

I get this dreadful error:

java.lang.IllegalStateException: Listeners cannot be used on the current thread. Realm cannot be automatically updated on a thread without a looper.

Ok, let's create a Scheduler with a Looper:

fun createSubscribeOnScheduler(): Scheduler {
    val t = HandlerThread("worker")
    if (!t.isAlive())
        t.start()
    return AndroidSchedulers.from(t.looper)
}

We can use it as such:

val subscribeOnScheduler = createSubscribeOnScheduler()
getAllPlayers()
    .subscribeOn(subscribeOnScheduler)
    .unsubscribeOn(subscribeOnScheduler)
    .observeOn(AndroidSchedulers.mainThread())

Now everything works just fine. However, who is going to kill that HandlerThread? What if getAllPlayer() is called simultaneously from multiple places? Do other (and better) solutions exist for querying Realm on a background thread using RxJava2?

0 Answers
Related