Reputation: 3488
I am trying to save data in Room and it requires some background thread to save data. So I have created an observable like this
val obs: Observable<MutableLiveData<List<Source>>>? = Observable.fromCallable(object :Callable<MutableLiveData<List<Source>>>{
override fun call(): MutableLiveData<List<Source>> {
return mutableLiveData
}
})
Then I am subscribing, observing and unsubscribing it like this
obs?.subscribeOn(Schedulers.io())?.observeOn(AndroidSchedulers.mainThread())?.unsubscribeOn(Schedulers.io())
?.subscribe(object : Observer<MutableLiveData<List<Source>>>{
override fun onComplete() {
}
override fun onSubscribe(d: Disposable?) {
}
override fun onNext(value: MutableLiveData<List<Source>>?) {
for(source in value!!.value!!.iterator()){
sourceDao.insert(source)//this is the line number 87, that logcat is pointing
}
}
override fun onError(e: Throwable?) {
e?.printStackTrace()
}
})
I am subscribing it on the Schedulers.io thread then observing it on the AndroidSchedulers.mainThread() but still I am getting not on background thread error. More specifically
Caused by: java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
at android.arch.persistence.room.RoomDatabase.assertNotMainThread(RoomDatabase.java:204)
at android.arch.persistence.room.RoomDatabase.beginTransaction(RoomDatabase.java:251)
06-18 11:11:08.674 3732-3732/com.theanilpaudel.technewspro W/System.err: at com.package.myapp.room.SourceDao_Impl.insert(SourceDao_Impl.java:63)
at com.package.myapp.main.MainRepository$saveToRoom$1.onNext(MainRepository.kt:87)
at com.package.myapp.main.MainRepository$saveToRoom$1.onNext(MainRepository.kt:76)
Upvotes: 1
Views: 1628
Reputation: 4060
It makes sense because you have observeOn
the main thread and you are doing your work in the observer (observeOn
manages the thread of the observer).
To fix this, you can use flatmap on your obs
and do the for loop in there. Since flatmap requires you to return an Observable, you can return Observable.just(true)
after your for loop.
Upvotes: 1
Reputation: 10279
Execute your DB operation within the Observable and not in your Observer:
val obs: Observable<MutableLiveData<List<Source>>>? = Observable.fromCallable(object :Callable<MutableLiveData<List<Source>>>{
override fun call(): MutableLiveData<List<Source>> {
for(source in mutableLiveData!!.value!!.iterator()){
sourceDao.insert(source)
}
return mutableLiveData
})
.subscribeOn(Schedulers.io())?.observeOn(AndroidSchedulers.mainThread())?.unsubscribeOn(Schedulers.io())
?.subscribe(object : Observer<MutableLiveData<List<Source>>>{
override fun onComplete() {
}
override fun onSubscribe(d: Disposable?) {
}
override fun onNext(value: MutableLiveData<List<Source>>?) {
// Nothing todo right more
}
override fun onError(e: Throwable?) {
e?.printStackTrace()
}
})
})
Upvotes: 2