2015-08-03 14 views
16

Po prostu zaczynam od RxJava/RxAndroid. Chcę uniknąć kontekst wycieka więc stworzyłem BaseFragment tak:Jaki jest właściwy sposób obsługi subskrypcji w RxJava/RxAndroid na cykl życia aktywności?

public abstract class BaseFragment extends Fragment { 

    protected CompositeSubscription compositeSubscription = new CompositeSubscription(); 

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

     compositeSubscription.unsubscribe(); 
    } 
} 

I w moim fragmentu, który rozciąga BaseFragment, robie to:

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; 
} 

Więc myślę, że moje pytanie jest dwojaki :

  1. Czy ten kontekst zostanie przerwany, ponieważ anuluję subskrypcję onDestroy()?

  2. I czy właściwie śledzę, czy obserwowalny jest "uruchomiony", ustawiając subskrypcję na wartość zerową po zakończeniu i sprawdzając nieważność?

Odpowiedz

11
  1. Tak, zatrzyma, ale należy również ustawić subskrypcję null w onError zbyt (lub po błędzie, nie będzie ponownie załadować przedmioty).

    Pamiętaj również, że fragment można zatrzymać, ale nie zniszczyć (na przykład w tylnym stosie), a w tym przypadku możesz nie chcieć obserwować . Jeśli przenosisz unsubscribe z onDestroy na onStop, nie zapomnij zainicjować compositeSubscription w onCreateView za każdym razem, gdy tworzony jest widok (ponieważ po anulowaniu subskrypcji CompositeSubs nie można już dodawać subskrypcji).

  2. Tak, zgadza się. Ale myślę, że compositeSubscription.remove można pominąć, ponieważ już sprawdziłeś, czy nie ma wartości null.

+0

więc jeśli mogę wypisać w OnStop i nigdy nie uaktualnia moje poglądy wtedy muszę ponownie uruchomić fetchNewObjects() w onResume? – Sree

+2

Ponadto, dlaczego onCreate? czy miałeś na myśliCreateView? – Sree

+0

Wolę zrobić w 'onCreate', ponieważ jest on wywoływany przed' onCreateView', więc compositeSubscription jest gotowy, zanim zostanie użyty – marwinXXII

5

Nie potrzebujesz żadnych lib innych firm do zarządzania cyklem życia Aktywności. Spróbuj wykonać następujące kody:

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); 
      } 
     }); 
    } 
} 

wydarzenia Lifecycle:

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

Zastosowanie:

myObservable 
    .compose(LifecycleBinder.subscribeUtilEvent(this, LifecycleEvent.ON_DESTROYED)) 
    .subscribe(); 
Powiązane problemy