当前位置: 首页 > 知识库问答 >
问题:

对于活动生命周期,在RxJava/RxAndroid中处理订阅的正确方法是什么?

安明亮
2023-03-14

我刚刚开始学习RxJava/RxAndroid。我想避免上下文泄漏,所以我创建了一个BaseFragment,如下所示:

public abstract class BaseFragment extends Fragment {

    protected CompositeSubscription compositeSubscription = new CompositeSubscription();

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

        compositeSubscription.unsubscribe();
    } 
} 

在我的扩展BaseFraank的片段中,我正在这样做:

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并检查null来正确跟踪可观察对象是否正在“运行”?

  • 共有2个答案

    司寇研
    2023-03-14

    您不需要任何第三方lib来管理活动生命周期。请尝试以下代码:

    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();
    
    汪弘光
    2023-03-14

    >

  • 是的,它会停止,但您也应该在onError中将订阅设置为null(或在错误后,您不会再次加载项目)。

    另外,不要忘记片段可以被停止,但不能被销毁(例如在后堆栈中),在这种情况下,您可能不想看到任何东西。如果每次创建视图时,都将取消订阅从onDestroy移动到onStop,请不要忘记在onCreateView中初始化compositeSubscription(因为取消订阅compositeSubscription后,您再也不能在那里添加订阅)。

    是的,正确。但是我认为复合ubscription.remove可以省略,因为您已经检查了null。

  •  类似资料:
    • 我知道当您订阅可观察时,您会收到一个必须使用Android生命周期取消订阅的订阅。因此,对于片段或活动中的订阅,我使用onDestroy()中的取消订阅。 但我的问题是,当我在没有任何生命周期的地方订阅时。例如,在SyncAdapter中。在这种情况下,我如何“自动取消订阅”以避免内存泄漏?在SyncAdapter中,有没有什么好的做法,比如说“永远不要在XXX位置订阅”,而我正在打破这种订阅?

    • 所以,我有一个组件 问题是,一旦组件被销毁,订阅是否仍然有效,或者Angular/RxJS是否足够聪明,可以自动取消订阅?

    • 我在开始新活动时遇到了一些问题。在我的应用程序中,我设置了侦听意图的广播接收器(屏幕关闭)。当屏幕关闭时,我的应用程序应该开始新活动(当然在某些情况下。我没有制作垃圾邮件应用程序)。但有时不是。 我在清单中声明了活动“singleTop”,所以我也重写了“onNewIntent”方法。(我认为这很重要)但事情是这样的。 当手机进入睡眠状态并且满足某些条件时,屏幕上会出现两个图标(“我的活动”)。我

    • 我为测试函数做了简单的应用程序,如onCreate()、onStart等。每个函数都让你有自己的日志。开始测试。 null 为什么在执行应用程序时调用onResume方法?(在a中) 为什么onPause和onStop方法一起调用?(在b中) 为什么在C中调用三个方法而不是onRestart或onrestume?(c) 为什么调用onDestroy方法?(d) 附言:对不起,英语:)

    • 方法的标注和函数类似: struct Owner(i32); impl Owner { // 标注生命周期,就像独立的函数一样。 fn add_one<'a>(&'a mut self) { self.0 += 1; } fn print<'a>(&'a self) { println!("`print`: {}", self.0); } } fn

    • 用法 组件和虚拟 DOM 节点都有生命周期方法,也叫钩子,它们会在 DOM 元素的生命周期的对应时期被调用。 // 组件中的钩子 var ComponentWithHook = { oninit: function(vnode) { console.log("initialize component") }, view: function() { return "hello