如何優雅地取消Retrofit請求?

我是綠色大米呀發表於2018-12-03

在實際開發中,頁面關閉,取消請求是很常見的需求,這裡分享一種簡單的實現方法。 我的思路是把網路請求和上下文的生命週期繫結。這裡用用到了Rxjava的Subject,Subject 既是 Observable 又是 Observer(Subscriber)。既可以發訊息也可以接收訊息。

我首先定義了幾個列舉,對應上下文的生命週期。

public enum ActivityLifeCycleEvent {
    CREATE,START,RESUME,PAUSE,STOP,DESTROY
}
複製程式碼

Fragment為例,在BaseFragment中,相應的生命週期回撥中發射訊息。


import rx.subjects.PublishSubject;

public abstract class BaseFragment extends Fragment {

    protected final PublishSubject<ActivityLifeCycleEvent> lifecycleSubject = PublishSubject.create();



    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onActivityCreated(savedInstanceState);
    }

    @Override
    public void onPause() {
        super.onPause();
        lifecycleSubject.onNext(ActivityLifeCycleEvent.PAUSE);
    }

    @Override
    public void onStop() {
        super.onStop();
        lifecycleSubject.onNext(ActivityLifeCycleEvent.STOP);
    }


    @Override
    public void onResume() {
        super.onResume();
        lifecycleSubject.onNext(ActivityLifeCycleEvent.RESUME);
    }


    @Override
    public void onDestroy() {
        super.onDestroy();
        lifecycleSubject.onNext(ActivityLifeCycleEvent.DESTROY);
    }

}

複製程式碼

一般情況下我們會使用Retrofit+Rxjava來進行網路請求,比如像下面這樣:

@Multipart
@POST(Urls.TIMER_GETUSERDETAIL_RX)
Observable<Results<User>> getUser(@PartMap Map<String, RequestBody> map);
複製程式碼

具體請求的時候可能是下面這樣

ApiService.instancce()
  .getUser(p.build())
  .takeUntil(bindLifeCycle(lifecycleSubject,ActivityLifeCycleEvent.DESTROY))
  .subscribe({
      ……
  })
複製程式碼

注意:下面這句話

.takeUntil(RxUtils.bindLifeCycle(lifecycleSubject, ActivityLifeCycleEvent.DESTROY))
複製程式碼

takeUntil一旦響應是成功它將自動終止源Observable於是停止向後端傳送資料。如果不是則繼續傳送請求。這裡如果收到ActivityLifeCycleEvent.DESTROY訊息,就會停止向後端傳送資料。

 public static Observable<ActivityLifeCycleEvent> bindLifeCycle(PublishSubject<ActivityLifeCycleEvent> lifecycleSubject, ActivityLifeCycleEvent bindEvent) {
        return  lifecycleSubject.takeFirst(activityLifeCycleEvent -> activityLifeCycleEvent.equals(bindEvent));
    }
複製程式碼

嗯,就這麼多。下面就是愉快地使用吧~

本方法只是取消了接受網路資料之後的後續操作,並不是真正停止了當前的請求哦~

相關文章