Ronil Raut
Ronil Raut

Reputation: 133

Android Room database RxAndroid, Exception : java.lang.IllegalStateException: Cannot access database on the main thread since

Currently, I am fetching data from Web API using RxAndroid and Retrofit, and want to store that Data in Room database but getting an exception

As I search and found that, room database operations won't work on UI thread so I added .subscribeOn(Schedulers.io()) in RXAndroid still it is throwing

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

public void onClickLogin(View view) {

             io.reactivex.Observable
             .zip(getLogin(Constants.EMAILID, Constants.PASSWORD),
             getUserInfo(Constants.EMAILID, Constants.PASSWORD),
            getProductDetails(Constants.EMAILID, Constants.PASSWORD).subscribeOn(Schedulers.io()),
                                .observeOn(AndroidSchedulers.mainThread())
                        new Function3<List<LoginModule>,
                                List<UserInfoModule>, ProductModule, AllZipData>() {
                            @Override
                            public AllZipData apply(List<LoginModule> loginModuleList, List<UserInfoModule> useerInfoModules, ProductModule productModule) throws Exception {

                                AllZipData allZipData = new AllZipData();
                                allZipData.setLoginModuleList(loginModuleList);
                                allZipData.setUserInfoModuleList(UserInfoModule);
                                allZipData.setProductModule(productModule);

                                return allZipData;
                            }
                        }).subscribe(new Observer<AllZipData>() {
            @Override
            public void onSubscribe(Disposable d) {
                compositeDisposable.add(d);
            }

            @Override
            public void onNext(AllZipData allZipData) {


                MyDatabase MyDatabase = MyDatabase.getInstance(context);

                for (int i = 0; i < allZipData.getUserInfoModuleList().size(); i++) {

                    UserInfoTable userInfoTable = new UserInfoTable();
                    userInfoTable.setValue1(allZipData.getUserInfoModuleList().get(i).getValue1());
                    userDatabase.userDao().insertUserInfo(userInfoTable);
                }

            }

            @Override
            public void onError(Throwable e) {
                Log.e(TAG, "onError: all zip data " + e.toString());
            }

            @Override
            public void onComplete() {
                Log.e(TAG, "onComplete: all data zipped");
            }
        });
}

how to solve this exception using RxAndroid.

How to add retryWhen();?

Upvotes: 4

Views: 2197

Answers (4)

Jignesh Mayani
Jignesh Mayani

Reputation: 7193

Use Map to perform operation. Check this

.subscribeOn(Schedulers.io())
        .map {
        }
        .observeOn(AndroidSchedulers.mainThread())
        .doOnSubscribe {

        }
        .subscribeWith(new DisposableObserver<AllZipData>() {
            @Override
            public void onSubscribe(Disposable d) {
                compositeDisposable.add(d);
            }

            @Override
            public void onNext(AllZipData allZipData) {

            }

            @Override
            public void onError(Throwable throwable) {

            }

        })

Upvotes: 0

akarnokd
akarnokd

Reputation: 69997

Where does this exception happen? If it is in onNext, that's because you specified observeOn(mainThread()) thus the database access happens on the main thread.

Try this

Observable.zip(
    getLogin(Constants.EMAILID, Constants.PASSWORD)
        .subscribeOn(Schedulers.io()),  // <--------------------------------
    getUserInfo(Constants.EMAILID, Constants.PASSWORD)
        .subscribeOn(Schedulers.io()),  // <--------------------------------
    getProductDetails(Constants.EMAILID, Constants.PASSWORD)
        .subscribeOn(Schedulers.io())   // <--------------------------------
)
.observeOn(Schedulers.io())             // <--------------------------------
.doOnNext(allZipData -> {
    MyDatabase MyDatabase = MyDatabase.getInstance(context);

    for (int i = 0; i < allZipData.getUserInfoModuleList().size(); i++) {

         UserInfoTable userInfoTable = new UserInfoTable();

         userInfoTable.setValue1(
             allZipData.getUserInfoModuleList().get(i).getValue1()
         );

         userDatabase.userDao().insertUserInfo(userInfoTable);
    }
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<AllZipData>() {
    @Override
    public void onSubscribe(Disposable d) {
        compositeDisposable.add(d);
    }

    @Override
    public void onNext(AllZipData allZipData) {
        // notify UI here?
    }

    @Override
    public void onError(Throwable e) {
        Log.e(TAG, "onError: all zip data " + e.toString());
    }

    @Override
    public void onComplete() {
        Log.e(TAG, "onComplete: all data zipped");
    }
});

Upvotes: 3

Manoj Perumarath
Manoj Perumarath

Reputation: 10214

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

Clearly says that you're running on MainThread of your application, which leads to freezing of the screen. You should handle your queries or long running operations on background thread of your application.

Change this

observeOn(AndroidSchedulers.mainThread())

to

observeOn(Schedulers.io())

Upvotes: 0

apksherlock
apksherlock

Reputation: 8371

I believe this line still needs some RxJava operations :

userDatabase.userDao().insertUserInfo(userInfoTable);

I believe the insertUserInfo in your dao should return a Completable.

Upvotes: 0

Related Questions