我有一个创建Presenter实例的活动。在Presenter层中,我从存储库中获取一个可观察的实例。然后,我使用Subscriber的子类订阅Observable,然后将结果订阅对象添加到CompositeSubscription。因为调用订阅服务器的onNext()后,我需要修改活动,所以我还将Presenter的引用传递给订阅服务器。
现在,我想知道引用是如何工作的,什么时候才有资格进行垃圾收集。
示例1:使用Subscriber订阅Observable,并将订阅添加到CompositeSubscription。在调用订阅服务器的onNext()之前,父活动将触发其onPause()生命周期事件。它告诉演示者点击暂停()并调用CompositeSubscription上的clear()。
此时复合订阅、订阅者和可观察有资格获得GC吗?或者在Presenter的onPawn()方法中,我是否需要显式地将对可观察、订阅者和复合订阅的引用归零?
示例2:
与示例1类似,演示者订阅了一个可观察对象,在调用Subscriber的onNext()方法之前,活动会经过onPause(),但这次也会经过onResume()。
因此,就像示例1中一样,演示者在onPause()中对CompositeSubscription调用clear()。
然后在onResume中发生以下情况:Presenter之前将可观察缓存在单例类中,因此在onResume中它可以看到缓存中有一个可观察的,这意味着可观察的从未完成运行。因此,Presenter现在创建了一个新的订阅者实例和一个新的CompositeSubscription实例,并使用订阅者和CompositeSubscription的新实例订阅缓存的可观察的。
但是现在我的问题是,我引入了内存泄漏吗?Subscriber的第一个实例引用了Presenter。当onResume()被调用时,我创建了Subscriber的第二个实例,Presenter引用了这个新实例。那么Subscriber的第一个实例会发生什么呢?它符合GC的条件吗?还是因为它引用了演示者但不再有指向它的引用而导致内存泄漏?
class Presenter {
private MyActivity mActivity;
private Repository mRepository;
private GlobalCache mGlobalCache;
private CompositeSubscription mCompSub;
public Presenter(MyActivity activity, Repository repository, GlobalCache globalCache) {
mActivity = activity;
mRepository = repository;
mGlobalCache = globalCache;
}
public void doLongRunningThing() {
Observable<Object> obs = mRepository.getObs();
mGlobalCache.retain(obs);
mCompSub = new CompositeSubscription();
MySubscriber subscriber = new Subscriber(this);
compSub.add(obs.subscribe(subscriber));
}
public void onResume() {
if (mGlobalCache.getObs() != null) {
Observable<Object> obs = mGlobalCache.getObs();
mCompSub = new CompositeSubscription();
MySubscriber subscriber = new Subscriber(this);
compSub.add(obs.subscribe(subscriber));
}
}
public void onPause() {
if(mCompSub != null && mCompSub.hasSubscriptions()) {
mCompSub.clear();
}
}
public void onDestroy() {
mActivity = null;
mRepository = null;
mGlobalCache = null;
}
public void handleResponse(Object object) {
activity.setUiToSomeState();
}
}
class MySubscriber extends Subscriber<Object> {
private Presenter mPresenter;
private GlobalCached mGlobalCache;
public MySubscriber(Presenter presenter, GlobalCache globalCache) {
mPresenter = presenter;
mGlobalCache = globalCache;
}
onCompleted() {
}
onError() {
}
onNext(Object object) {
mGlobalCache.clearObs();
mPresenter.handleResponse(object);
}
}
示例1:
假设您的意思是这里没有保存引用的“缓存”:
本示例中没有泄漏。关于GC,订阅者对象可以被GC’d(释放),因为再也没有对象对其进行引用了,但是,CompositeSubscription引用由presenter持有,我假设该presenter由活动持有(对于Observable可能相同,示例中不清楚),所以当活动持有对该对象的引用时,它们的GC取决于它们的父活动。直到活动本身不再由任何人举办
(旁注:已完成的活动与暂停/停止的活动之间存在差异,在前一种情况下,系统将在不再需要此活动时尽快尝试GC,而在后一种情况下,只要有必要,系统将保留该活动)
示例2:
虽然您有一个(静态假设)缓存,但由于您在onPause取消了对可观察对象的订阅,可观察对象没有对演示者/活动的引用,因此不会发生活动泄漏。在现实生活场景中,这仍然取决于这个可观察对象或任何操作符应用于他的内容,这意味着如果链中的某个地方有活动/演示者对象的引用,则可能存在泄漏。
除此之外,我建议您始终进行测试,以确保没有遗漏任何内容,您可以使用adb dumpsys meminfo并观察活动的计数,简单的打开和关闭(完成)活动多次可以指示泄漏,此外,Square的优秀人员还提供了LeakCanary库,可以在调试时自动报告活动泄漏。
我担心从泄漏金丝雀回来的信息。它显示了在UI上声明的所有变量,如片段中的材料按钮、材料卡片视图、文本视图、图像视图等,都导致了内存泄漏。我不知道为什么会这样。
问题内容: 我认为我的android应用正在泄漏内存。我不是绝对确定这是问题所在。 应用程序打开时经常崩溃,并且logcat尝试加载位图图像时会显示“内存不足”异常。 崩溃后,我重新打开了该应用程序,它运行正常。Logcat会显示许多“ gc”,并且JIT表会不时地向上调整大小,而不会向下调整,直到应用程序因内存不足错误而崩溃。 这听起来像是内存泄漏吗?如果是这样,我该如何定位和关闭泄漏点。 这是
我正在Android应用程序中使用一些本机库,我想在某个时间点从内存中卸载它们。当装入本机库的类的类装入器被垃圾回收时,库被卸载。灵感:本土卸载。 如果ClassLoader用于加载某些类(可能导致内存泄漏),则不会收集垃圾。 本机库只能在应用程序中的一个ClassLoader中加载。如果仍然有旧的ClassLoader挂在内存中的某个地方,并且一个新的ClassLoader试图在某个时间点加载相
我正在使用libgdx制作一个实时壁纸应用程序,根据时间改变资产。对于e、 g从早上6点到下午6点,我有“早上图形”,之后我有“晚上图形”,从下午6点到早上6点。 我构建资产的方式如下 我有12个AtlasRegion类型的静态数组,1个静态纹理区域变量和1个静态纹理变量。 我有两个静态函数load晨()和loadEnight()用于加载资产。 在funcions中,我加载如下 对于所有数组,如果
本文向大家介绍Android 内存溢出和内存泄漏的问题,包括了Android 内存溢出和内存泄漏的问题的使用技巧和注意事项,需要的朋友参考一下 Android 内存溢出和内存泄漏的问题 在面试中,经常有面试官会问“你知道什么是内存溢出?什么是内存泄漏?怎么避免?”通过这篇文章,你可以回答出来了。 内存溢出 (OOM)是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;
我正在玩rxjava,发现如果在活动被销毁之前没有完成订阅,则存在内存泄漏的风险,因为“可观察对象保留对上下文的引用”。如果订阅没有取消订阅,则此类情况的演示之一如下所示。已销毁(来源:https://github.com/dlew/android-subscription-leaks/blob/master/app/src/main/java/net/danlew/rxsubscriptions