android中常见内存溢出原因:
1.数据库的cursor没有关闭。
2.adapter没有缓存/复用contentview
3.调用registerReceiver后没有unregisterReceiver;
4.没有关闭inputstream/outputstream。
5.Bitmap使用后没有调用recycle();
6.Context泄漏
7.读取bitmap对象过大
8.static关键字等。
直接引起内存泄漏:
public class ClassName {
private static Context mContext;
//省略
}
// 如果mContext 被赋值,那么对应的context对象无法被释放,将引起内存泄漏。内存泄漏严重的时候会导致oom
间接引起内存泄漏:
private static Drawable sBackground;
@Override
protected void onCreate(Bundle state) {
super.onCreate(state);
TextView label = new TextView(this);
label.setText("Leaks are bad");
if (sBackground == null) {
sBackground = getDrawable(R.drawable.large_bitmap);
}
label.setBackgroundDrawable(sBackground);
setContentView(label);
}
/*虽然并没有显式的保存context的引用,但是drawable与view连接之后,drawable将view设置为一个回调,而view持有context对引用,所以引链如下:
Drawable->TextView->Context
所以context同样无法释放,最终引起内存泄漏。
*/
内部类持有外部对象引起内存泄漏:
public class BasicActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new MyThread().start();
}
private class OneThread extends Thread{
@Override
public void run() {
super.run();
//do somthing
}
}
}
由于OneThread 持有外部对象,所以在run函数没有结束时,OneThread不会被销毁,同样外部对象也不会被销毁,因此就出现了内存泄漏的问题。
而AsyncTask的情况会更严重,因为它内部维持了一个线程池,那么AsyncTask产生的thread的声明周期是不稳定的,因此如果AsyncTask作为acitvity的内部类,就更容易出现内存泄漏的问题,所以一般不建议将AsyncTask作为内部类使用。
如何解决:将内部类改为静态内部类,并且内部类中使用弱引用保存Context引用。
bitmap内存泄露解决方法:
及时回收
设置采样率,没有必要全部展示的截取一部分展示
选取合适的分辨率,对图片进行压缩
巧用软引用,防止内存泄漏
其他:
及时关闭InputStream/OutputStream
及时关闭cursor
用registerReceiver()后生命周期结束时调用unregisterReceiver()