简体   繁体   English

在onDettachView中放置Observable

[英]Disposing Observables in onDettachView

I'm facing the famous IllegalStateException problem in my app. 我在应用程序中遇到著名的IllegalStateException问题。 The problem stems after a network request (using Retrofit) is done, returning me an Observable. 问题发生在完成网络请求(使用翻新)后,返回一个Observable。 I'm using the excellent Mosby framework to handle MVP stuff, here is my code: 我正在使用出色的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());
            }
        }
    }

The exception I'm getting from Crashlytics is: 我从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)

My questions: Is it right to dispose Observables in the detachView method ? 我的问题:在detachView方法中放置Observables是否正确? From what I understand, the detachView is called when the frag (I'm using it with frags) onDestroyView is called, right after onStop (where the state gets checked by Android). 据我了解,当onStop(Android会检查状态)之后,在调用碎片(我在碎片中使用它)onDestroyView时会调用detachView。 If not, should I create a dispose method in my presenter and call it from my frag onStop ? 如果没有,我是否应该在演示者中创建一个dispose方法并从我的片段onStop调用它?

Thanks ! 谢谢 !

I think detachView() is the correct event to dispose, if you would dispose at onStop() - where ever your activity stopped the query will cancelled. 我认为detachView()是要处理的正确事件,如果您要在onStop()处进行处理-无论您的活动停止在哪里,查询都将被取消。 from UX perspective, that's means that if user started a query, then got a phone call, or switch to another app and comes back, the query will not continue and he must trigger it again and wait inside the app. 从UX的角度来看,这意味着如果用户启动了查询,接了电话或者切换到另一个应用并返回,则查询将不会继续,他必须再次触发它并在应用内等待。

as for this problem, even if you would dispose at onStop() , it will not solve the problem as onSaveInstanceState() is called before onStop() . 对于此问题,即使您将其放置在onStop() ,也不会解决问题,因为onSaveInstanceState()会在onStop()之前onStop()

This is a general common Fragments issue, when you commit fragment transaction after onSaveInstance() , and should be solved at Fragments level, you can see here various solutions, like using commitAllowingStateLoss() for instance: 这是一个常见的常见Fragments问题,当您在onSaveInstance()之后提交片段事务时,应在Fragments级别解决,您可以在此处看到各种解决方案,例如使用commitAllowingStateLoss()
IllegalStateException: Can not perform this action after onSaveInstanceState with ViewPager IllegalStateException:使用ViewPager在onSaveInstanceState之后无法执行此操作

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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