内存泄漏通过onConfigurationChanged()

时间:2014-12-12 00:45:39

标签: android memory-leaks

我有一个AsyncTask,如果用户执行Switch Color等配置,我需要“重启”。

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

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

AsyncTask我向我的EditText添加onTextChangeListener!(后来导致MemoryLeak)。

为了防止MemoryLeaks我的AsyncTask中有一个方法,删除了onTextChangedListener

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

除非我旋转设备,否则一切正常。当我旋转设备时,我只在onConfigurationChanged

中执行此操作
myWorkerClass.clearMemory();
            myWorkerClass = new WorkerClass(getApplicationContext(), gv, searchbar, width, scaleButtonText);
            myWorkerClass.execute();

正如您所看到的,我做的完全相同,就像用户更改颜色一样。 在旋转设备上我正在泄漏内存,在切换颜色时我不是!

这是在切换颜色后:

enter image description here

这是在旋转屏幕几次之后(请记住我与切换颜色完全一样:

enter image description here

这些是来自堆转储的泄漏嫌疑人:

enter image description here

enter image description here

这是我的统治者树 enter image description here

为什么我知道onTextChangeListener是问题?

因为如果我评论将onTextChangedListener添加到我的EditText中,一切正常。没有记忆泄漏。

我的问题:

当我以完全相同的方式启动asynctask并在asynctask中执行相同的操作时,为什么旋转更改泄漏内存和颜色更改不会?

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

但我无法弄清楚这是不是我的问题。 Rotation必须做一些不同的事情,比如创建一个新的活动,因为它创建了一个对我的edittext的新引用。因此,他无法移除旧的onTextChangeListener

请理解。我不想公开我的整个代码。但我认为在这种情况下无论如何都没有必要。

2 个答案:

答案 0 :(得分:0)

  

旋转必须做一些不同的事情,比如创建一个新的活动,因为它创建了一个对我的edittext的新引用。

确切地说,它会破坏您当前的活动并创建一个新的活动。如果searchbar是AsyncTask的成员变量,那么考虑将其放入WeakReference:

WeakReference<SearchBar> searchbarPtr; 

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

另外请记住不要让AsyncTask成为您活动的内部类。如果它是嵌套的,那么将其设置为静态。否则你的asynctask将继续引用你的活动,它将阻止它被销毁 - 直到它的线程结束。

在所有情况下,不可否认地使所有工作都非常困难和耗时。

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

答案 1 :(得分:0)

在android中,旋转会破坏您当前的活动以启动新活动 为避免这种情况,您可以在清单文件中添加android:configChanges="orientation|screenSize"

以下是避免轮换更改时内存泄漏的提示

  1. 不要保留对上下文活动的长期引用(对活动的引用应与活动本身具有相同的生命周期)。
  2. 尝试使用context-application而不是context-activity
  3. 如果您不控制其生命周期,请避免活动中的非静态内部类,使用静态内部类并对内部活动进行弱引用。这个问题的解决方案是使用带有WeakReference的静态内部类到外部类,就像在ViewRoot和它的W内部类中所做的那样
  4. 垃圾收集器不是防止内存泄漏的保险
  5. 来源:Avoiding memory leaks