我阅读了一些关于如何避免Android内存泄漏的文章,但我仍然不确定我是否做对了。
Activity
。onCreate()
内启动的。Context
或View
s。在我的onDestroy()
方法中,我将所有这些实例设置为null。Bitmap
s。Q1 :这够了吗?
令我困惑的是你可以在网上找到的禁忌的经典例子(http://www.curious-creature.org/2008/12/18/avoid-memory-leaks-on-android/):
@Override
protected void onCreate(Bundle state) {
super.onCreate(state);
TextView label = new TextView(this);
label.setText("Leaks are bad");
setContentView(label);
}
我认为,只要onCreate
完成,label
就会超出范围并且已经过GCed。
Q2 :这怎么会造成内存泄漏?
我的活动基本上是这样的:
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/* Statics */
AssetUtils.initIndex(this);
BitmapLoader.startInstance(this);
/* frame */
ViewGroup frame = (ViewGroup) getLayoutInflater().inflate(R.layout.frame, null);
this.setContentView(frame);
/* create controller */
Controller controller = new Controller(frame, getLayoutInflater());
/* START */
controller.start();
}
@Override
public void onDestroy() {
super.onStop();
/* Statics */
AssetUtils.destroyInstance();
BitmapLoader.destroyInstance();
}
内部Controller
我偶尔使用Context
检索View#getContext()
,将其传递给手动创建的View
等。它永远不会静态地存储在某个地方,只会存在于所有返回Controller
的类的成员变量中。
Q3 :有什么我忽略的吗?
答案 0 :(得分:22)
Q1。你已经脱离了背景(没有开玩笑的意思:)。
如果您看到原始文章,泄漏实际上发生在引入位图字段的下一代码片段中。 Roman然后清楚地解释了为什么泄漏。您显示的代码不会泄漏。
http://www.curious-creature.org/2008/12/18/avoid-memory-leaks-on-android/
Q2。仅在没有其他选择的情况下使用Activity上下文,并且绝不允许在范围大于其引用的Activity范围的内容中引用它。你所展示的代码并没有泄漏,因为没有任何上下文引用的范围大于你的Activity。你怀疑它确实存在吗?
Q3。当使用Bitmaps,静态引用或不使用静态引用时,我习惯在onPause()中从视图中取消绑定Bitamps(请记住onDestroy()不能保证,但它有点无关紧要,好像你被摧毁一样,你的进程被杀了所以GC不是一个问题)。链接的文章还解释了如何执行此操作。我已将其作为处理位图的任何活动的模板模式。
[编辑]
抱歉,我刚刚检查过。这篇文章没有说明如何解开。这是我使用的模式:
@Override
protected void onPause()
{
super.onPause();
unbindDrawables(findViewById(R.id.mainLayout));
System.gc();
}
@Override
protected void onDestroy()
{
super.onDestroy();
unbindDrawables(findViewById(R.id.mainLayout));
System.gc();
}
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();
}
}
mainLayout
是活动布局的根视图。
我包括onDestroy()因为我可以手动完成()我的Activity。
请注意。调用system.gc()是一个复杂的主题,可能想要省略它。这里有一些很好的讨论为什么它可能不是一件好事,主要关注性能。但是,在我看来,当一项活动被破坏时,暗示现在是执行GC的好时机不会造成伤害。在破坏活动的开销中,将不必要地调用它的效率低下。