在 RxJava/RxAndroid 中为 Activity 生命周期处理订阅的正确方法是什么?
What is the proper way to handle subscriptions in RxJava/RxAndroid for an Activity Lifecycle?
我才刚刚开始 RxJava/RxAndroid。我想避免上下文泄漏,所以我创建了一个 BaseFragment,如下所示:
public abstract class BaseFragment extends Fragment {
protected CompositeSubscription compositeSubscription = new CompositeSubscription();
@Override
public void onDestroy() {
super.onDestroy();
compositeSubscription.unsubscribe();
}
}
在我扩展 BaseFragment 的片段中,我这样做:
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;
}
所以我想我的问题有两个方面:
这是否会因为我取消订阅 onDestroy() 而阻止上下文泄漏?
我是否通过在完成后将订阅设置为 null 并检查无效性来正确跟踪可观察对象是否 "running"?
是的,它会停止,但你也应该在onError
中设置订阅null
(或者在错误后,你不会再次加载项目)。
另外不要忘记片段可以停止,但不能销毁
(例如,在后台堆栈中)您可能不想观察
在这种情况下的任何事情。
如果您将 unsubscribe
从 onDestroy
移动到 onStop
,请不要忘记在每次创建视图时在 onCreateView
中初始化 compositeSubscription
(因为取消订阅 CompositeSubscription 后您不再可以在那里添加订阅)。
没错。但我认为 compositeSubscription.remove
可以省略,因为你已经检查了 null.
您不需要任何 third-party 库来管理 Activity 生命周期。请尝试以下代码:
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);
}
});
}
}
生命周期事件:
public enum LifecycleEvent {
ON_PAUSED,
ON_STOPPED,
ON_SAVE_INSTANCE_STATE,
ON_DESTROYED,
ON_VIEW_DESTORYED,
ON_DETACHED,
}
用法:
myObservable
.compose(LifecycleBinder.subscribeUtilEvent(this, LifecycleEvent.ON_DESTROYED))
.subscribe();
我才刚刚开始 RxJava/RxAndroid。我想避免上下文泄漏,所以我创建了一个 BaseFragment,如下所示:
public abstract class BaseFragment extends Fragment {
protected CompositeSubscription compositeSubscription = new CompositeSubscription();
@Override
public void onDestroy() {
super.onDestroy();
compositeSubscription.unsubscribe();
}
}
在我扩展 BaseFragment 的片段中,我这样做:
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;
}
所以我想我的问题有两个方面:
这是否会因为我取消订阅 onDestroy() 而阻止上下文泄漏?
我是否通过在完成后将订阅设置为 null 并检查无效性来正确跟踪可观察对象是否 "running"?
是的,它会停止,但你也应该在
onError
中设置订阅null
(或者在错误后,你不会再次加载项目)。另外不要忘记片段可以停止,但不能销毁 (例如,在后台堆栈中)您可能不想观察 在这种情况下的任何事情。 如果您将
unsubscribe
从onDestroy
移动到onStop
,请不要忘记在每次创建视图时在onCreateView
中初始化compositeSubscription
(因为取消订阅 CompositeSubscription 后您不再可以在那里添加订阅)。没错。但我认为
compositeSubscription.remove
可以省略,因为你已经检查了 null.
您不需要任何 third-party 库来管理 Activity 生命周期。请尝试以下代码:
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);
}
});
}
}
生命周期事件:
public enum LifecycleEvent {
ON_PAUSED,
ON_STOPPED,
ON_SAVE_INSTANCE_STATE,
ON_DESTROYED,
ON_VIEW_DESTORYED,
ON_DETACHED,
}
用法:
myObservable
.compose(LifecycleBinder.subscribeUtilEvent(this, LifecycleEvent.ON_DESTROYED))
.subscribe();