我已经开发了一个Android应用程序,而且我正处于手机应用程序开发阶段,其中一切似乎都运行良好,你想宣布胜利和发货,但你知道必须有一些记忆和资源泄漏; Android上只有16mb的堆,而且在Android应用程序中显然很容易泄漏。
我一直在环顾四周,到目前为止我们只能挖掘'hprof'和'traceview'的信息,而且没有得到很多好评。
您遇到或开发了哪些工具或方法,并且可能需要在OS项目中共享?
答案 0 :(得分:90)
我发现开发Android应用程序时最常见的错误之一是“java.lang.OutOfMemoryError:Bitmap Size Exceeds VM Budget”错误。在更改方向后,我在使用大量位图的活动中发现了这个错误:活动被销毁,再次创建,布局从消耗可用于位图的VM内存的XML中“膨胀”。
垃圾收集器未正确释放先前活动布局上的位图,因为它们已经交叉引用了它们的活动。经过多次实验,我发现了一个很好的解决方案。
首先,在XML布局的父视图上设置“id”属性:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/RootView"
>
...
然后,在Activity的onDestroy()方法中,调用unbindDrawables()方法将refence传递给父View,然后执行System.gc()
@Override
protected void onDestroy() {
super.onDestroy();
unbindDrawables(findViewById(R.id.RootView));
System.gc();
}
private void unbindDrawables(View view) {
if (view.getBackground() != null) {
view.getBackground().setCallback(null);
}
if (view instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
unbindDrawables(((ViewGroup) view).getChildAt(i));
}
((ViewGroup) view).removeAllViews();
}
}
这个unbindDrawables()方法以递归方式探索视图树:
答案 1 :(得分:29)
获取Eclipse Memory Analyzer(http://www.eclipse.org/mat/) 检查http://kohlerm.blogspot.com/2010/02/android-memory-usage-analysis-slides.html 和http://kohlerm.blogspot.com/search/label/memory
答案 2 :(得分:28)
主要针对未来的Google旅行者:
遗憾的是,大多数java工具都不适用于此任务,因为它们只分析JVM-Heap。但是,每个Android应用程序也都有一个本机堆,它也必须符合~16 MB的限制。例如,它通常用于位图数据。所以你可以很容易地运行Out Of Memory错误,即使你的JVM-Heap是大约3 MB的chillin,如果你使用了大量的drawables。
答案 3 :(得分:20)
如果您只使用位图背景,@ hp.android的答案效果很好,但在我的情况下,我有BaseAdapter
为{{1}提供一组ImageView
s }。我按照建议修改了GridView
方法,以便条件为:
unbindDrawables()
但问题是递归方法永远不会处理if (view instanceof ViewGroup && !(view instanceof AdapterView)) {
...
}
的子节点。为了解决这个问题,我改为做了以下几点:
AdapterView
以便仍然处理if (view instanceof ViewGroup) {
ViewGroup viewGroup = (ViewGroup) view;
for (int i = 0; i < viewGroup.getChildCount(); i++)
unbindDrawables(viewGroup.getChildAt(i));
if (!(view instanceof AdapterView))
viewGroup.removeAllViews();
}
的子项 - 该方法不会尝试删除所有子项(不受支持)。
这并不能解决问题,因为AdapterView
管理的位图不是他们的背景。因此,我添加了以下内容。它并不理想但它有效:
ImageView
总的来说,if (view instanceof ImageView) {
ImageView imageView = (ImageView) view;
imageView.setImageBitmap(null);
}
方法是:
unbindDrawables()
我希望有一种更有原则的方法来释放这些资源。
答案 4 :(得分:12)
关于Android内存管理的良好Google I / O演讲(2011),以及有关内存分析的工具+技术的详细信息:
http://www.youtube.com/watch?v=_CruQY55HOk
答案 5 :(得分:4)
Valgrind已被移植到Android(由Mozilla赞助)。请参阅Valgrind on Android — Current Status和Support Running Valgrind for Android on ARM(评论67)。
答案 6 :(得分:1)
嗯,这些是与Android使用的独特格式相关联的工具。我认为您可能不满意的是正在使用的基础测试代码框架。
您是否尝试使用Android Mock Framework模拟测试代码区域?