简体   繁体   中英

IllegalStateException using Room and RxJava

I'm having an issue when accesing the Room DAOs in my app. I get this error even though I'm doing the operation in a background thread via rxjava:

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

I'm trying to use a clean architecture via MVP in the app and I call the use case that make that operation in a background thread.

More info:

The classes involverd are:

RecipesPresenter.java

UpdateRecipes.java which extends from UseCase.java .

And finally RecipesLocalDataSource.java

I need some help here, thanks in advance.

You are using just which takes an already created/computed value. So basically you do the computation on the caller thread and you wrap the result into an Observable . (I can't imagine why this logical misunderstanding comes up so often as there is no mainstream language that would defer a calculation between a regular parenthesis.)

Do like this instead:

@Override
public Observable<Boolean> updateRecipes(List<JsonRecipe> jsonRecipes) {
    return Observable.fromCallable(() -> {
        mRecipeDb.runInTransaction(() ->
            deleteOldAndInsertNewRecipesTransaction(jsonRecipes));
        return true;
    });
}

Using RxJava does not mean you´re doing Async process, in fact RxJava is sync by default.

If you want make an operation async you need to use operators subscribeOn which will subscribe your observable to be run in another thread, or use observerOn to specify which operation you want to be done async.

An example

/**
 * Once that you set in your pipeline the observerOn all the next steps of your pipeline will be executed in another thread.
 * Shall print
 * First step main
 * Second step RxNewThreadScheduler-2
 * Third step RxNewThreadScheduler-1
 */
@Test
public void testObservableObserverOn() throws InterruptedException {
    Subscription subscription = Observable.just(1)
            .doOnNext(number -> System.out.println("First step " + Thread.currentThread()
                    .getName()))
            .observeOn(Schedulers.newThread())
            .doOnNext(number -> System.out.println("Second step " + Thread.currentThread()
                    .getName()))
            .observeOn(Schedulers.newThread())
            .doOnNext(number -> System.out.println("Third step " + Thread.currentThread()
                    .getName()))
            .subscribe();
    new TestSubscriber((Observer) subscription)
            .awaitTerminalEvent(100, TimeUnit.MILLISECONDS);
}

You can see some examples of both here https://github.com/politrons/reactive/blob/master/src/test/java/rx/observables/scheduler/ObservableAsynchronous.java

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM