问题描述
我一直面临着一些恼人的 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的内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!