Search code examples
androidrx-javaandroid-roomrx-android

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();?


Solution

  • 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");
        }
    });