【问题标题】:Android Room database RxAndroid, Exception : java.lang.IllegalStateException: Cannot access database on the main thread sinceAndroid Room 数据库 RxAndroid,异常:java.lang.IllegalStateException:无法访问主线程上的数据库,因为
【发布时间】:2019-08-07 07:00:27
【问题描述】:

目前,我正在使用 RxAndroid 和 Retrofit 从 Web API 获取数据,并希望将该数据存储在 Room 数据库中,但出现异常

我搜索并发现,房间数据库操作在 UI 线程上不起作用,所以我在 RXAndroid 中添加了.subscribeOn(Schedulers.io()) 还是在扔

java.lang.IllegalStateException:无法访问主线程上的数据库,因为它可能会长时间锁定 UI。

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

如何使用 RxAndroid 解决这个异常。

如何添加retryWhen();?

【问题讨论】:

    标签: android rx-java android-room rx-android


    【解决方案1】:

    这个异常发生在哪里?如果在onNext,那是因为你指定了observeOn(mainThread()),所以数据库访问发生在主线程上。

    试试这个

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

    【讨论】:

    • 如何添加retryWhen()?
    • 在哪里,为什么,如何,什么?
    • 每当网络调用抛出 IO 异常我必须重试 3 次
    • 请单独提问。
    • 我已经发布了单独的问题stackoverflow.com/questions/57429527/…
    【解决方案2】:

    我相信这条线还需要一些RxJava 操作:

    userDatabase.userDao().insertUserInfo(userInfoTable);
    

    我相信你的 dao 中的 insertUserInfo 应该返回一个 Completable。

    【讨论】:

    • 这是我在接口@Insert void insertUserInfo (UserInfo userInfo); 中编写的代码;
    【解决方案3】:

    java.lang.IllegalStateException:无法访问主线程上的数据库,因为它可能会长时间锁定 UI。

    明确表示您正在MainThread 上运行您的应用程序,这会导致屏幕冻结。您应该在应用程序的后台线程上处理您的查询或长时间运行的操作。

    改变这个

    observeOn(AndroidSchedulers.mainThread())
    

    到

    observeOn(Schedulers.io())
    

    【讨论】:

      【解决方案4】:

      使用Map进行操作。检查这个

      .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) {
      
                  }
      
              })
      

      【讨论】:

        猜你喜欢
        • 2017-11-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-21
        相关资源
        最近更新 更多