Распространение Observables в onDettachView

Я сталкиваюсь с известной проблемой IllegalStateException в моем приложении. Проблема связана с выполнением сетевого запроса (с использованием Retrofit), возвращающего мне Observable. Я использую отличный фреймворк Mosby для работы с MVP, вот мой код:

public class CarAdPresenterCustomer extends CarAdPresenterAbstract {

    private final GetCarByIdUseCase getCarByIdUseCase;
    private final GetCarMatchDetailsUseCase getCarMatchDetailsUseCaseUseCase;

    public CarAdPresenterCustomer(GetCarByIdUseCase getCarByIdUseCase, GetCarMatchDetailsUseCase getCarMatchDetailsUseCaseUseCase) {
        this.getCarByIdUseCase = getCarByIdUseCase;
        this.getCarMatchDetailsUseCaseUseCase = getCarMatchDetailsUseCaseUseCase;
    }

    public void getCarMatchDetails(String carId) {

        if (isViewAttached()) {
            getView().showLoading();
        }
        getCarMatchDetailsUseCaseUseCase.execute(new GetCarMatchDetailsSubscriber(), new GetCarMatchDetailsUseCase.Params(carId));
    }

    public void getCarDetails(String carId) {
        getCarByIdUseCase.execute(new GetCarByIdSubscriber(), new GetCarByIdUseCase.Params(carId));
    }

    @Override
    public void detachView(boolean retainInstance) {
        getCarByIdUseCase.dispose();
        getCarMatchDetailsUseCaseUseCase.dispose();
        super.detachView(retainInstance);
    }

    private class GetCarByIdSubscriber extends DefaultObserver<DefaultCarResponse> {

        @Override
        public void onNext(DefaultCarResponse carResponse) {
            if (carResponse != null) {
                if (isViewAttached()) {
                    getView().hideLoading();
                    getView().inflateCarUiComponents(carResponse.getCar());
                }
            }
        }

        @Override
        public void onError(Throwable exception) {
            if (isViewAttached()) {
                getView().hideLoading();
                getView().showErrorMessage(exception.getMessage());
            }
        }
    }

Исключение, которое я получаю от Crashlytics:

Fatal Exception: java.lang.IllegalStateException: Fatal Exception thrown on Scheduler.
       at io.reactivex.android.schedulers.HandlerScheduler$ScheduledRunnable.run(HandlerScheduler.java:111)
       at android.os.Handler.handleCallback(Handler.java:739)
       at android.os.Handler.dispatchMessage(Handler.java:95)
       at android.os.Looper.loop(Looper.java:145)
       at android.app.ActivityThread.main(ActivityThread.java:6843)
       at java.lang.reflect.Method.invoke(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:372)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)
Caused by java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
       at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1884)
       at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1902)
       at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:650)
       at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:609)
       at android.support.v4.app.DialogFragment.show(DialogFragment.java:143)
       at br.com.moobie.android.emailConfirmation.ui.fragment.EmailConfirmationFragment.showEmailConfirmationError(EmailConfirmationFragment.java:202)
       at br.com.moobie.android.emailConfirmation.presenter.EmailConfirmationPresenterImpl$GetUserSubscriber.onNext(EmailConfirmationPresenterImpl.java:75)
       at br.com.moobie.android.emailConfirmation.presenter.EmailConfirmationPresenterImpl$GetUserSubscriber.onNext(EmailConfirmationPresenterImpl.java:63)
       at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.drainNormal(ObservableObserveOn.java:200)
       at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.run(ObservableObserveOn.java:252)
       at io.reactivex.android.schedulers.HandlerScheduler$ScheduledRunnable.run(HandlerScheduler.java:109)
       at android.os.Handler.handleCallback(Handler.java:739)
       at android.os.Handler.dispatchMessage(Handler.java:95)
       at android.os.Looper.loop(Looper.java:145)
       at android.app.ActivityThread.main(ActivityThread.java:6843)
       at java.lang.reflect.Method.invoke(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:372)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)

Мои вопросы: правильно ли располагать Observables в методе detachView? Насколько я понимаю, detachView вызывается при вызове фрагмента (я использую его с фрагами) onDestroyView сразу после onStop (где состояние проверяется Android). Если нет, должен ли я создать метод dispose в моем докладчике и вызвать его из моего фрагмента onStop?

Спасибо!

1 ответ

Решение

Я думаю detachView() является правильным событием, если вы располагаете на onStop() - где бы ваша деятельность не остановилась, запрос будет отменен. с точки зрения UX, это означает, что если пользователь запустил запрос, затем получил телефонный звонок или переключился на другое приложение и вернулся, запрос не будет продолжен, и он должен снова запустить его и подождать внутри приложения.

что касается этой проблемы, даже если бы вы располагали onStop(), это не решит проблему, так как onSaveInstanceState()называется раньше onStop(),

Это общая распространенная проблема фрагментов, когда вы фиксируете транзакцию фрагмента после onSaveInstance()и должны быть решены на уровне фрагментов, вы можете увидеть здесь различные решения, такие как использование commitAllowingStateLoss() например:
IllegalStateException: не может выполнить это действие после onSaveInstanceState с ViewPager

Другие вопросы по тегам