2015-08-03 20 views
16

Tôi chỉ mới bắt đầu sử dụng RxJava/RxAndroid. Tôi muốn tránh bối cảnh rò rỉ vì vậy tôi đã tạo ra một BaseFragment như vậy:Cách thích hợp để xử lý đăng ký trong RxJava/RxAndroid cho Vòng đời hoạt động là gì?

public abstract class BaseFragment extends Fragment { 

    protected CompositeSubscription compositeSubscription = new CompositeSubscription(); 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 

     compositeSubscription.unsubscribe(); 
    } 
} 

Và bên trong mảnh vỡ của tôi mà kéo dài BaseFragment, tôi đang làm điều này:

protected void fetchNewerObjects(){ 
     if(!areNewerObjectsFetching()){ //if it is not already fetching newer objects 

      Runtime.getRuntime().gc();//clean out memory if possible 

      fetchNewObjectsSubscription = Observable 
       .just(new Object1()) 
       .map(new Func1<Object1, Object2>() { 
        @Override 
        public Object2 call(Object1 obj1) { 
         //do bg stuff 
         return obj2; 
        } 
       }) 
       .subscribeOn(Schedulers.io()) 
       .observeOn(AndroidSchedulers.mainThread()) 
       .subscribe(new Observer<Object2>() { 
        @Override 
        public void onCompleted() { 
         compositeSubscription.remove(fetchNewObjectsSubscription); 
         fetchNewObjectsSubscription = null; 
        } 

        @Override 
        public void onError(Throwable e) { 

        } 

        @Override 
        public void onNext(ArrayList<NewsFeedObject> newsFeedObjects) { 
         //do stuff 
        } 
       }); 

     //add subscription to composite subscription so it can be unsubscribed onDestroy() 
     compositeSubscription.add(fetchNewObjectsSubscription); 
    } 
} 

protected boolean areNewerObjectsFetching(){ 
    if(fetchNewObjectsSubscription == null || fetchNewObjectsSubscription.isUnsubscribed()){ //if its either null or is in a finished status 
     return false; 
    } 
    return true; 
} 

Vì vậy, tôi đoán câu hỏi của tôi là hai lần :

  1. Ngữ cảnh dừng này có bị rò rỉ vì tôi hủy đăng kýDestroy() không?

  2. Và tôi có theo dõi đúng thời điểm có thể quan sát được là "đang chạy" không bằng cách đặt đăng ký thành vô giá trị sau khi hoàn thành và kiểm tra tính rỗng?

Trả lời

11
  1. Vâng, nó sẽ dừng lại, nhưng bạn cũng nên đặt thuê bao null trong onError quá (hoặc sau khi lỗi, bạn sẽ không tải các mặt hàng một lần nữa).

    Cũng đừng quên rằng đoạn có thể được dừng lại, nhưng không bị phá hủy (trong ngăn xếp lưng, ví dụ) và bạn có thể không muốn quan sát bất kỳ điều gì trong trường hợp này. Nếu bạn di chuyển unsubscribe từ onDestroy đến onStop đừng quên khởi tạo compositeSubscription trong onCreateView mỗi lần xem được tạo (vì sau khi CompositeSubscription bị hủy đăng ký, bạn không còn có thể thêm đăng ký ở đó).

  2. Có chính xác. Nhưng tôi nghĩ rằng compositeSubscription.remove có thể được bỏ qua, bởi vì bạn đã kiểm tra null.

+0

vì vậy nếu tôi bỏ đăng ký trong onStop, và nó không bao giờ cập nhật quan điểm của tôi sau đó tôi sẽ cần phải tái chạy fetchNewObjects() trong onResume? – Sree

+2

Ngoài ra, tại sao là onCreate? ý của bạn là onCreateView? – Sree

+0

Tôi thích làm trong 'onCreate' vì nó được gọi trước' onCreateView', vì vậy compositeSubscription đã sẵn sàng trước khi nó được sử dụng – marwinXXII

5

Bạn không cần bất kỳ lib của bên thứ ba nào để quản lý vòng đời hoạt động. Hãy thử các mã sau:

public class LifecycleBinder { 

    public static <R> Observable.Transformer<R, R> subscribeUtilEvent(final Activity target, LifecycleEvent event) { 
     final Application app = target.getApplication(); 
     final PublishSubject<LifecycleEvent> publishSubject = PublishSubject.create(); 
     final Application.ActivityLifecycleCallbacks callbacks = new Application.ActivityLifecycleCallbacks() { 
      @Override 
      public void onActivityCreated(Activity activity, Bundle savedInstanceState) { 

      } 

      @Override 
      public void onActivityStarted(Activity activity) { 

      } 

      @Override 
      public void onActivityResumed(Activity activity) { 

      } 

      @Override 
      public void onActivityPaused(Activity activity) { 
       if (activity == target) 
        publishSubject.onNext(LifecycleEvent.ON_PAUSED); 
      } 

      @Override 
      public void onActivityStopped(Activity activity) { 
       if (activity == target) 
        publishSubject.onNext(LifecycleEvent.ON_STOPPED); 
      } 

      @Override 
      public void onActivitySaveInstanceState(Activity activity, Bundle outState) { 
       if (activity == target) 
        publishSubject.onNext(LifecycleEvent.ON_SAVE_INSTANCE_STATE); 
      } 

      @Override 
      public void onActivityDestroyed(Activity activity) { 
       if (activity == target) 
        publishSubject.onNext(LifecycleEvent.ON_DESTROYED); 
      } 
     }; 

     app.registerActivityLifecycleCallbacks(callbacks); 
     return subscribeUtilEvent(publishSubject, event, new Action0() { 
      @Override 
      public void call() { 
       app.unregisterActivityLifecycleCallbacks(callbacks); 
      } 
     }); 
    } 

    public static <R> Observable.Transformer<R, R> subscribeUtilEvent(final Fragment target, LifecycleEvent event) { 
     final FragmentManager manager = target.getFragmentManager(); 
     if (manager == null) { 
      throw new NullPointerException("fragment manager is null!"); 
     } 

     final PublishSubject<LifecycleEvent> publishSubject = PublishSubject.create(); 
     final FragmentManager.FragmentLifecycleCallbacks callbacks = manager.new FragmentLifecycleCallbacks() { 

      @Override 
      public void onFragmentPreAttached(FragmentManager fm, Fragment f, Context context) { 
      } 

      @Override 
      public void onFragmentAttached(FragmentManager fm, Fragment f, Context context) { 
      } 

      @Override 
      public void onFragmentCreated(FragmentManager fm, Fragment f, Bundle savedInstanceState) { 
      } 

      @Override 
      public void onFragmentActivityCreated(FragmentManager fm, Fragment f, Bundle savedInstanceState) { 
      } 

      @Override 
      public void onFragmentViewCreated(FragmentManager fm, Fragment f, View v, Bundle savedInstanceState) { 
      } 

      @Override 
      public void onFragmentStarted(FragmentManager fm, Fragment f) { 
      } 

      @Override 
      public void onFragmentResumed(FragmentManager fm, Fragment f) { 
      } 

      @Override 
      public void onFragmentPaused(FragmentManager fm, Fragment f) { 
       if (f == target) 
        publishSubject.onNext(LifecycleEvent.ON_PAUSED); 
      } 

      @Override 
      public void onFragmentStopped(FragmentManager fm, Fragment f) { 
       if (f == target) 
        publishSubject.onNext(LifecycleEvent.ON_STOPPED); 
      } 

      @Override 
      public void onFragmentSaveInstanceState(FragmentManager fm, Fragment f, Bundle outState) { 
       if (f == target) 
        publishSubject.onNext(LifecycleEvent.ON_SAVE_INSTANCE_STATE); 
      } 

      @Override 
      public void onFragmentViewDestroyed(FragmentManager fm, Fragment f) { 
       if (f == target) 
        publishSubject.onNext(LifecycleEvent.ON_VIEW_DESTORYED); 
      } 

      @Override 
      public void onFragmentDestroyed(FragmentManager fm, Fragment f) { 
       if (f == target) 
        publishSubject.onNext(LifecycleEvent.ON_DESTROYED); 
      } 

      @Override 
      public void onFragmentDetached(FragmentManager fm, Fragment f) { 
       if (f == target) 
        publishSubject.onNext(LifecycleEvent.ON_DESTROYED); 
      } 
     }; 
     manager.registerFragmentLifecycleCallbacks(callbacks, true); 

     return subscribeUtilEvent(publishSubject, event, new Action0() { 
      @Override 
      public void call() { 
       manager.unregisterFragmentLifecycleCallbacks(callbacks); 
      } 
     }); 
    } 

    private static <R, T> Observable.Transformer<R, R> subscribeUtilEvent(final Observable<T> source, final T event, final Action0 doOnComplete) { 
     return new Observable.Transformer<R, R>() { 
      @Override 
      public Observable<R> call(Observable<R> rObservable) { 
       return rObservable.takeUntil(takeUntilEvent(source, event)).doOnCompleted(doOnComplete); 
      } 
     }; 
    } 

    private static <T> Observable<T> takeUntilEvent(final Observable<T> src, final T event) { 
     return src.takeFirst(new Func1<T, Boolean>() { 
      @Override 
      public Boolean call(T lifecycleEvent) { 
       return lifecycleEvent.equals(event); 
      } 
     }); 
    } 
} 

Vòng đời các sự kiện:

public enum LifecycleEvent { 
    ON_PAUSED, 
    ON_STOPPED, 
    ON_SAVE_INSTANCE_STATE, 
    ON_DESTROYED, 
    ON_VIEW_DESTORYED, 
    ON_DETACHED, 
} 

Cách sử dụng:

myObservable 
    .compose(LifecycleBinder.subscribeUtilEvent(this, LifecycleEvent.ON_DESTROYED)) 
    .subscribe(); 
Các vấn đề liên quan