内存泄漏
一、单利泄漏
存在内存泄露问题的一些代码片段像下面这样:
public class Util {
private Context mContext;
private static Util sInstance;
private Util(Context context) {
this.mContext = context;
}
public static Util getInstance(Context context) {
if (sInstance == null) {
sInstance = new Util(context);
}
return sInstance;
}
}
假设Activity A 里使用Util类:
Util.getInstance(this);
代码大意就是这样,这样写的问题就是,在Activity A 里使用Util类,传入的context 是 actvitiy-context。试想一下,当Activity A 生命周期结束,但Util类里面却还存在A的引用 (mContext),这样Activity A占用的内存就一直不能回收,而A的对象也不会再被使用。本人写代码测试过,在A中调用了finish(),A的destroy()方法也被执行了,但其占用的内存,比如说,ImageView占用的内存,还是不能释放的。
那么如何解决这个问题呢?在A中,可以用Util.getInstance(getApplicationContext());或Util.getInstance(getApplication()); 代替。
因为Application的生命周期是贯穿整个程序的,所以Util类持有它的引用,也不会造成内存泄露问题。
2、资源使用完未关闭
一、动态注册广播,一定要在onDestroy 调用unregisterReceiver 取消注册,不然当activity结束后,广播不被回收,导致内存泄漏。
二、io Cursor 流要记得close,一定要在finally去close 防止抛异常没执行close 。
三、bitmap 使用时要记录recycle,不注意,很容易出现ANR。
3、Handler造成内存泄露,
方法一:通过程序逻辑来进行保护。
1.在关闭Activity的时候停掉你的后台线程。线程停掉了,就相当于切断了Handler和外部连接的线,Activity自然会在合适的时候被回收。
2.如果你的Handler是被delay的Message持有了引用,那么使用相应的Handler的removeCallbacks()方法,把消息对象从消息队列移除就行了。
方法二:将Handler声明为静态类。
4、AsyncTask内存泄露
在销毁当前Activity的时候手动去调用AsyncTask的cancle方法,(activity 结束后,AsyncTask会在doInBackground()方法执行完毕之后再结束)
内存优化
1、尽量使用StringBuilder,不要用"+"去拼接字符串,浪费不必要的内存。
2、图片能压缩,尽量压缩。
3、尽量使用池:线程池,缓存池,okhttp里面的connectionPool(Socket复用池),okio SegmentPool(buffer复用池)------(可以重复 使用对象,减少内存开销,内存拉动,cpu开销)
4、常用的数据结构优化: 能用SparseArray就不用HashMap.
5、xml层级和view :xml层级最好控制在5层以内,多用ViewStub ,include,merge。