Search code examples
android-studioasynchronousrx-javaandroid-room

How do I replace Asynctask with RxJava Observer?


I have a test project with Room database. Using Asynctask I can successfully insert an object with some test data into the database. I'm trying to learn RxJava and replace Asynctask with RxJava's observer, but it doesn't work. I have read alot of documentation and watched tutorials, but I don't think I quite get it. Here's the relevant code:

Here I set my Room object with the data from my List:

for(ObjectForArray item: listToDatabase) {
        myRoomEntity.setName( item.getName() );
        Log.d( "TAG", myRoomEntity.getName() );
    }

Then I try to use RxJava Observable to insert data into the database. This was originally and successfully done using Asynctask:

Observable<MyRoomEntity> myRX = Observable
            .just(myRoomEntity)
            .subscribeOn( Schedulers.io() )
            .observeOn( AndroidSchedulers.mainThread() );

myRX.subscribe( new Observer<MyRoomEntity>() {
        @Override
        public void onSubscribe(Disposable d) {
            Log.d("TAG ONSUBSCRIBE", d.toString());

            try {
                myViewModel.insertDatabase( myRoomEntity );
                Log.d( "TAG", "Populating database Success" );
            }catch(Error error) {
                Log.d( "TAG", error.toString() );
            }
        }

The OnNext, OnError and OnComplete are empty.

When I run the project it crashes with the error:

Cannot access database on the main thread since it may potentially lock the UI for a long period of time.

I'm obviously using RxJava wrong since the point is to do asynchronous tasks away from the main thread.


Solution

  • Please try restructuring your code like this:

    Completable.fromAction(() -> myViewModel.insertDatabase(myRoomEntity))
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(() -> Log.d("TAG", "Populating database Success"),
                            throwable -> Log.d("TAG", throwable.toString()))
    

    Considerations:

    1. If your myRoomEntity is not available before this whole construct gets subscribed, make sure you use defer http://reactivex.io/documentation/operators/defer.html
    2. Your subscribe section handlers are operating on "main", that's why you were receiving a crash.
    3. If possible, avoid unnecessary just calls