通过onConfigurationChanged()的MemoryLeak [英] MemoryLeak through onConfigurationChanged()

查看:76
本文介绍了通过onConfigurationChanged()的MemoryLeak的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个AsyncTask,如果用户执行诸如Switch Color之类的配置,我需要重新启动".

当他这样做时,我像这样启动AsyncTask:

myWorkerClass.clearMemory();
    myWorkerClass = new WorkerClass(getApplicationContext(), gv, searchbar, width, scaleButtonText);
    myWorkerClass.execute();

AsyncTask中,将onTextChangeListener添加到我的EditText!(稍后导致MemoryLeak).

为了防止MemoryLeaks泄漏,我在AsyncTask中有一个方法可以删除onTextChangedListener:

public void clearMemory() {
    searchbar.removeTextChangedListener(myTextWatcher);
}

一切正常,除非我旋转设备.旋转设备时,我只能在onConfigurationChanged中进行此操作:

myWorkerClass.clearMemory();
            myWorkerClass = new WorkerClass(getApplicationContext(), gv, searchbar, width, scaleButtonText);
            myWorkerClass.execute();

如您所见,我所做的事情与用户更改颜色完全相同. 但是,在旋转设备上我正在泄漏内存,在切换颜色时我不在!

这是在切换颜色之后:

这是在旋转屏幕几次之后(请记住,我所做的操作与切换颜色时完全相同:

这些是我从堆转储中泄漏的嫌疑犯:

这是我的主宰树:

为什么我知道onTextChangeListener是问题?

因为如果我将onTextChangedListener添加到EditText中,则一切正常.没有内存泄漏.

我的问题:

为什么当我以完全相同的方式启动asynctask并在asynctask中执行完全相同的操作时,轮换更改"泄漏内存和颜色更改"为什么没有?

我搜索了一下: http://developer.android .com/guide/topics/resources/runtime-changes.html

但是我不知道这是否是我的问题. Rotation必须做一些不同的事情,例如创建一个新的活动,因为它创建了对我的edittext的新引用.因此,他无法删除旧的onTextChangeListener.

请谅解.我不想公开我的整个代码.但是我认为在这种情况下这不是必需的.

解决方案

Rotation必须做一些不同的事情,例如创建新活动,因为它创建了对我的edittext的新引用.

确实,它会破坏您的当前活动并创建一个新活动.如果searchbar是您的AsyncTask的成员变量,请考虑将其放入WeakReference中:

WeakReference<SearchBar> searchbarPtr; 

然后使用searchBarPtr.get()进行访问,但检查其是否为null,如果是,则意味着它由于配置更改而被垃圾回收.

还请记住不要将AsyncTask设置为活动的内部类.如果是嵌套的,则使其为静态.否则,您的asynctask将继续引用您的活动,并防止该活动被破坏-直至其线程结束.

不幸的是,要使其在所有情况下都能正常工作可能非常困难且耗时.

希望没有人会建议通过android:configChanges防止破坏您的活动,在轮换过程中实现行为的正确行为将防止它在不太常见的活动生命周期中崩溃/泄漏,而这是android:configChanges无法阻止的.

I have an AsyncTask which I need to "restart" if the user does configurations such as Switch Color.

When he do so I start the AsyncTask like this:

myWorkerClass.clearMemory();
    myWorkerClass = new WorkerClass(getApplicationContext(), gv, searchbar, width, scaleButtonText);
    myWorkerClass.execute();

In the AsyncTask I add a onTextChangeListener to my EditText!(Which causes the MemoryLeak later).

To prevent MemoryLeaks I have a Method in my AsyncTask which removes the onTextChangedListener:

public void clearMemory() {
    searchbar.removeTextChangedListener(myTextWatcher);
}

Everything works fine except when I rotate my device. When I rotate my Device I do only this in onConfigurationChanged:

myWorkerClass.clearMemory();
            myWorkerClass = new WorkerClass(getApplicationContext(), gv, searchbar, width, scaleButtonText);
            myWorkerClass.execute();

As you can see I do exactly the same thing as if the user changes a Color. But at rotating device I'm leaking Memory, at switching Color I'm not!

This is after switching the Color:

This is after rotating the Screen a few times (remember I do exactly the same as at switching color:

These are my Leak Suspects from the Heap Dump:

This is my dominator tree:

Why do I know the onTextChangeListener is the Problem?

Because if I comment adding a onTextChangedListener to my EditText out, everything works fine. No Memory Leaks.

My Question:

Why does a Rotation Change leak Memory and a Color Change does not when I start the asynctask the exact same way and do exact the same things within the asynctask?

I searched a little bit: http://developer.android.com/guide/topics/resources/runtime-changes.html

But I can't figure out if that is my Problem. The Rotation must do something different, like creating a new activity because of that creating a new reference to my edittext. And because of that he can't remove the old onTextChangeListener.

Please understand. I don't want to make my whole code public. But I think this isn't necessary anyway in this case.

解决方案

The Rotation must do something different, like creating a new activity because of that creating a new reference to my edittext.

exactly, it destroys your current activity and creates a new one. If searchbar is a member variable of your AsyncTask then consider putting it into WeakReference:

WeakReference<SearchBar> searchbarPtr; 

then access using searchBarPtr.get(), but check if its null, if so then it means it was garbage collected due to config change.

Also remember to not make your AsyncTask an inner class of you activity. If it is nested then make it static. Otherwise your asynctask will keep reference to your activity and it will prevent it from being destroyed - until its thread ends.

Unfortuanately making it all work corectly in all situations can be quite difficult and time consuming.

Hopefully no one will suggest preventing destruction of your activity through android:configChanges, implementing correct behaviour of your activity during rotation will prevent it from crashing/leaking in less common activity lifecycle moments which cannot be prevented by android:configChanges.

这篇关于通过onConfigurationChanged()的MemoryLeak的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆