本文介绍了茫然不知一个(可能的)Android的内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直面临着一些恼人的 OutOfMemoryError异常,甚至还要保证我所有的位图正确缩放等等。其实之后,这个问题似乎并没有被相关位图所有,但我可能是错的。

I’ve been facing some annoying OutOfMemoryErrors, even after making sure that all my Bitmaps are properly scaled etc. In fact, the issue doesn’t seem to be related to Bitmaps at all, but I may be wrong.

有关测试和故障隔离的目的,我一直在两项活动(姑且称之为主和List)之间用我的抽屉式导航(不使用后退按钮切换)。我可以在DDMS看到,分配的内存约180每次我回时间增加KB。

For testing and error-isolation purposes, I’ve been switching between two activities (let’s call them Main and List) using my Navigation Drawer (not using the back button). I can see in the DDMS that the allocated memory increases around 180 KB every time I return.

我已经做了内存转储和使用Eclipse的MAT来分析时间3不同点:

I’ve done memory dumps and used eclipse MAT to analyze 3 different points in time:

我怀疑是内存泄漏,但我真的不能找出其原因。根据内存转储,它看起来像它的剩女和 java.lang.FinalizerReference 的不断增加。在用户的也有很多 FinalizerReferences 在他的内存转储,但答案是不太清楚。

I suspect a memory leak but I can’t really find out its cause. According to the memory dumps, it looks like it’s the "Remainder" and java.lang.FinalizerReference that keep increasing. The user in this question also has a lot of FinalizerReferences in his memory dump, but the answer isn't quite clear.

泄漏嫌疑人报告我在时间的最后点进行,都没有被怀疑 android.content.res.Resources 和 android.graphics.Bitmap 这似乎并不在增长随着时间的推移:

The Leak Suspects Report I made in the last point in time isn’t very helpful as it suspects of android.content.res.Resources and android.graphics.Bitmap which don’t seem to be growing over time:

在的报告(可悲的是,这里没有present)我见过 android.widget.ListView 13个实例几个尖锐作为一个潜在的泄露嫌疑。

In one of the reports (sadly, not present here) I've seen 13 instances of android.widget.ListView pointed as a potential leak suspect.

这些内存增加发生与活动(不只是主和List我在这个例子中使用)之间的任何过渡。

These memory increases happen with any transition between activities (not just the Main and List I used in this example).

我如何能找到(无明显吗?)内存泄漏?我一直在抓我的头很长一段时间,所以任何的帮助和提示,将是巨大的。

How can I find the (non-obvious?) memory leak? I’ve been scratching my head for a long time so any help and tips would be great.


  • 位图(@ OrhanC1):我在评论上述两项活动的任何位图实例和内存仍然增加。内存转储仍然显示一些位图,但我相信他们会与我所分配的资源,而不是实际的位图。

  • Bitmaps (@OrhanC1): I've commented any Bitmap instantiations in the two activities mentioned above and the memory still increases. The memory dump still shows some bitmaps but I believe they're related to resources and not actual bitmaps allocated by me.

关于自定义字体(@erakitin):我使用他们,但我保持每个字样的一个实例在我的应用上下文中使用一个单例(公共类MyApp的扩展应用)。我试着来评论字体的任何引用上面提到的两个活动和记忆仍增加了。

Regarding custom fonts (@erakitin): I'm using them, but I'm keeping a single instance of each Typeface in my Application context (public class MyApp extends Application) using a singleton. I've tried commenting any references to the fonts in the two activities mentioned above and the memory still increases.

我不认为我泄露上下文(@DigCamara):我不举行这两项活动中的任何静态引用,我使用应用米背景下,而不是活动的除了在一个适配器。如果我留在同一个活动并做一些屏幕旋转,内存不增加。

I don't think I'm leaking the Context (@DigCamara): I don't hold any static references inside these two Activities, I'm using the Application context instead of the Activity's except in an adapter. If I stay in the same Activity and do some screen rotations, the memory doesn't increase.

在@基于NickT的评论:我可以看到我都活动的许多实例。可以将这些内存是增加的增加背部栈的活动的数量,而不是一个内存泄漏的(我虽然OS处理的是,apparently不的)?如果我使用 FLAG_ACTIVITY_REORDER_TO_FRONT 意图标志,则内存只会增加,直到所有不同的活动已经被实例化(一次)。有用的这个问题:Android不是从堆栈杀伤活性,当内存不足。

Based on @NickT's comment: I can see I have many instances of both activities. Could these memory increases be just the result of an increase in the number of activities of the back stack and not a memory leak (I though the OS dealt with that, apparently not)? If I use the FLAG_ACTIVITY_REORDER_TO_FRONT intent flag then the memory only increases until all different activities have been instantiated (once). Useful for this matter: Android not killing activities from stack when memory is low.

推荐答案

它看起来像为什么的增长是数量增长的原因<$ C (在后面的堆栈$ C>活动实例如目录的13实例活动 +主<$ C的13实例$ C>活动)。

It looks like the reason why the Remainder is growing is the growth of the number of Activity instances in the back stack (e.g. 13 instances of the "List" Activity + 13 instances of the "Main" Activity).

我已经改变了我的抽屉式导航栏,这样,当用户点击主页按钮(带他到应用程序的仪表板)我设置了 Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK 标志:活动被重复使用及背面堆栈被清除(的)。其实,我已经这样做了,因为我不想控制板(家)活动中创建的多个实例。

I've changed my Navigation Drawer so that when the user clicks the "Home" button (which takes him to the App's "Dashboard") I set the Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK flags: the Activity is re-used and the back stack is cleared (as recommended by the Android guidelines, actually). In fact, I should have done this already as I don't want several instances of the Dashboard ("Home") activity to be created.

通过这样做,我可以看到,活动被破坏,分配的堆的大小(包括剩余切片)减小:

By doing this I can see that the Activities are destroyed and allocated heap size (including the "Remaining" slice) decreases:

虽然解决这个,我也注意到,我的活动和它使用的位图的一个没有被破坏,即使后面的堆栈已被清理(泄漏)。与MAT分析后,我得出的结论是这个子问题的根源是一个参考的ImageView 我保存在活动。通过添加此code到的onStop()的方法,我已经成功地得到的活性和位图被摧毁:

While fixing this, I also noticed that one of my Activities and a Bitmap used by it were not being destroyed, even if the back stack had been cleared (leak). After analysing with MAT I concluded that the source of this sub-problem was a reference to an ImageView that I kept in the Activity. By adding this code to the onStop() method, I've managed to get both the activity and Bitmap to be destroyed:

@Override
protected void onStop() {
    super.onStop();

    ImageView myImage = (ImageView) findViewById(R.id.myImage );
    if(myImage .getDrawable() != null)
        myImage.getDrawable().setCallback(null);

    RoundedImageView roundImage = (RoundedImageView) findViewById(R.id.roundImage); // a custom View
    if(roundImage.getDrawable() != null)
        roundImage.getDrawable().setCallback(null);


}

然后我全身所有的活动 FragmentActivity 让他们称之为 unbindDrawables(查看视图)的onDestroy()

private void unbindDrawables(View view)
{
    if (view.getBackground() != null)
    {
        view.getBackground().setCallback(null);
    }
    if (view instanceof ViewGroup && !(view instanceof AdapterView))
    {
        for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++)
        {
            unbindDrawables(((ViewGroup) view).getChildAt(i));
        }
        ((ViewGroup) view).removeAllViews();
    }
}

感谢@NickT指着我在正确的方向。

Thanks to @NickT for pointing me in the right direction.

这篇关于茫然不知一个(可能的)Android的内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-27 06:51