

3.内存优化
Android的虚拟机是基于寄存器的Dalvik,其最大堆大小通常很小(最低端设备为16M,后来的设备为24M,48M等),因此我们可以使用的内存空间为有限。如果我们的内存使用量超过一定限制,则会发生OutOfMemory错误。
以下情况可能导致内存溢出:
错误使用静态变量
如果变量是静态变量,则它属于整个类,而不是该类的特定实例,因此静态变量的生命周期特别长。如果静态变量引用了一些资源密集型实例,例如Context,则存在内存溢出的风险。

Google Developer Blog给出了一个示例,专门介绍了由于长期引用Context导致的内存溢出情况。
示例代码:
private static Drawable sBackground; @Override protected void onCreate(Bundle state) { super.onCreate(state); TextView textView = new TextView(this); textView.setText("Leaks are bad"); if (sBackground == null) { sBackground = getResources().getDrawable(R.drawable.large_bitmap); } textView.setBackgroundDrawable(sBackground); setContentView(textView); }
在这种情况下,静态sBackground变量没有显式保存Context引用,但是当我们执行view.setBackgroundDrawable(Drawable drawable);时,drawable对象将通过View.setCallback()将当前视图设置为回调。此)方法。
有关详细信息,请参见View类的源代码:
public void setBackgroundDrawable(Drawable background) {
//...
if (mBackground == null || mBackground.getMinimumHeight() != background.getMinimumHeight() ||
mBackground.getMinimumWidth() != background.getMinimumWidth()) {
requestLayout = true;
}
background.setCallback(this);
if (background.isStateful()) {
background.setState(getDrawableState());
}
background.setVisible(getVisibility() == VISIBLE, false);
mBackground = background;
//...
}

background.setCallback(this);代码块就是我们所说的set回调。
因此,在这种情况下,将存在这样的隐式引用链:Drawable持有View,而View持有Context,sBackground是静态的,并且生命周期特别长,这将导致Context溢出。
解决方案:
1.不使用活动上下文,而是使用应用程序上下文;
private static Drawable sBackground; @Override protected void onCreate(Bundle state) { super.onCreate(state); TextView textView = new TextView(this.getApplication()); textView.setText("Leaks are bad"); if (sBackground == null) { sBackground = getResources().getDrawable(R.drawable.large_bitmap); } textView.setBackgroundDrawable(sBackground); setContentView(textView); }
2.在onDestroy()方法中,释放Activity和Drawable之间的绑定关系,从而删除Drawable对Activity的引用,以便可以回收Context;

长时期内部类和匿名内部类长时间保存外部类引用,导致相关资源无法释放
长周期内部类,匿名内部类,例如Handler,Thread,AsyncTask等。
HandlerOutOfMemoryActivity显示由Handler引起的内存溢出。
ThreadOutOfMemoryActivity显示由线程引起的内存溢出。
由AsyncTask引起的内存溢出,如AsyncTaskOutOfMemoryActivity所示。
位图引起的内存溢出

通常,这是由于试图将太大的图片加载到内存中或内存中已有太多图片而导致的,导致内存溢出。
游标未关闭
在通常情况下,如果查询获得的数据量很小,则不会有内存问题,并且虚拟机可以保证最终释放Cusor。如果Cursor的数据量非常大,尤其是其中包含Blob信息,则应确保及时释放Cursor占用的内存,而不要等待GC处理。
由单例模式引用上下文导致的内存泄漏
如果您使用Singleton实例= Singleton.getInstance(this);在一个活动中,它将导致该活动被Singleton引用并且无法被释放。目前,正确的方法是使用getApplicationContext()替换Activity的Context,以避免内存泄漏。
代码中的一些细节
最后,我整理了一些可能在开发过程中导致内存溢出的方案,将它们放在com.cundong.memory.demo.wrong中,并给出了优化方法,将它们放在com.cundong.memory.demo.right中。
4.屏幕截图

本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/shoujiruanjian/article-326456-1.html
盯住日本动态
没必要咬文嚼字地批判
唱的太好了