Search code examples
androidmobileandroid-roomrx-android

RX android Single<Boolean> not subscribing to Schedulers.io() thread but to main thread instead when doing ROOM query


I am not very experienced in using android RX. I am checking if an entity exits in ROOM using this query

this is in my DAO

   @Query("SELECT EXISTS(SELECT * FROM contacts WHERE number = :phoneNumber)")
    fun exists(phoneNumber: Long) : Boolean

and this is in my RepoImpl

   override fun checkContactExists(number: Long): Single<Boolean> {
        val exists = database.ContactsDao().exists(number)
        return Single.fromCallable{
            exists
        }
    }

and I call this is a presenter like so:

   repo.checkContactExists(number)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : DisposableSingleObserver<Boolean>(){
                override fun onSuccess(exists: Boolean) {
                    Log.d(TAG, "contacts exists $exists")
                    if (exists) {
                        ....
                    } else {
                        ....
                    }
                }

                override fun onError(e: Throwable) {
                    Log.e(TAG, "failed to check if number exists ${e.message}")
                }
            })

and when I call this I get this exception

2021-03-09 10:22:04.052 13966-13966/com.umony.radar E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.umony.radar, PID: 13966
    java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
        at androidx.room.RoomDatabase.assertNotMainThread(RoomDatabase.java:261)
        at androidx.room.RoomDatabase.query(RoomDatabase.java:303)
        at androidx.room.util.DBUtil.query(DBUtil.java:54)

Can anyone help me understand why the query is executed on the main thread when I have the subscribeOn(Schedulers.io())


Solution

  • correct your method checkContactExists as below. it will work.

    override fun checkContactExists(number: Long): Single<Boolean> {
        return Single.fromCallable{
             database.ContactsDao().exists(number)
        }
    }