The Room database of my app is wrapped in a RxJava2 data access layer that modifies all Singles, Maybes, etc. to subscribeOn the Schedulers.io() scheduler, and observeOn the AndroidSchedulers.mainThread() scheduler.
This was considered to be a good idea because sometimes Android misbehaves if you attempt to modify the UI from off of the main thread, which is the typical behavior upon completion of a query.
public <T> Maybe<T> flow(Maybe maybe) {
return maybe
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
I now have a part of my app which requires a synchronous retrieval of an element from the database. My design didn't anticipate this. When I execute #blockingGet(), I get deadlock which I've read about in other questions like this one.
Is there any way to modify the stream to not actually observeOn the main thread in the edge case where I need to synchronously retrieve some data? Or will I have to re-evaluate this design entirely, to let each individual invocation decide which Scheduler is used to observeOn?
--
In my Activity, upon interacting with a UI element:
Book book = mBooksDataSource.getBookWithId(1L)
.observeOn(Schedulers.io())
.blockingGet();
Log.d(LOG_TAG, "I am here."); //Never reached
In the DataSource:
public Maybe<Book> getBookWithId(long bookId) {
return mReservoir.flow(mBooksDao.getBookWithId(bookId));
//The reservoir is the class containing the flow method from further above.
}
In the BooksDao:
@Transaction @Query("SELECT ...")
public abstract Maybe<Book> getBookWithId(long bookId);
I think Sanlok Lee's comment is correct, and you're calling blockingGet()
on the main thread. which is ignoring schedulers. As such, you can use an ExecutorService
, or try the following:
Schedulers.io().scheduleDirect(() -> {
final Book book = mBooksDataSource.getBookWithId(1L).blockingGet();
//Do something with the book
});