我刚刚开始学习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来正确跟踪可观察对象是否正在“运行”?
您不需要任何第三方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();
>
是的,它会停止,但您也应该在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