Android中的内存泄露与优化有很多方面
例如:
数据库cursor没有关闭
注册机制造成的内存泄露
输入/输出流没有关闭
Context造成的内存泄露
Adapter中没有缓存convertView
Bitmap对象没有使用recycle进行释放
集合中的数据没有及时释放
Handle的内存泄露
findViewById等等问题
Context的内存泄露
例如:在activity中启动线程 service或者其他有自己声明周期的对象持有activity的引用等等
在activity中启动线程 线程的生命周期是不可控的 在线程中通常会进行一些耗时操作 我们在activity中直接启动一个线程 那么此时线程就持有了activity的引用(内部类会持有外部类的引用) 如果我们在线程中进行一些耗时操作 在线程中的耗时操作完成之前activity是不能被销毁的 如果我们频繁的启动退出该activity 就会造成内存的不断泄露 最终导致OOM
解决方案 将线程内部类改为static
外部引用activity的context 此时只要外部这个对象没有被销毁 activity就不能被销毁 造成持续的内存泄露
解决方案 尽量使用application的context代替activity中的context 或者在引用context的时候使用weakreference(弱引用)
Adapter中没有使用convertView
在adapter中 每加载一个item 就会执行一次getView方法 如果在getView方法中 不使用convertView进行缓存的话 每加载一个item 就要重新解析一次layout布局文件 耗时又浪费系统资源
Adapter的getView方法中为我们提供了convertView 即当listView中最上边的item移出屏幕时 系统会将该View进行分类回收 以备我们进行重用 当我们使用convertView时 就会大大减少解析xml文件浪费的时间 同时又尽可能少的占据系统资源 在使用convertView的同时 应当使用viewHolder 注意使用convertView和使用ViewHolder是不同的 使用convertView是为了减少解析xml文件浪费的时间 而使用ViewHolder是为了减少findViewById浪费的时间
Bitmap对象
Bitmap对象是非常占据系统资源的 现在的手机 数码相机像素越来越高 照出来的照片也是越来越大 2-3M是平常 如果我们在程序中不对这样的图片进行处理的话 一张照片就可以让我们的程序直接OOM
通常 我们在使用bitmap显示图片的时候 都会对图片进行压缩处理 加载大图片的时候 先加载图片的边界 再根据手机的像素对图片进行压缩处理 批量加载小图片的时候 在对图片进行压缩的同时 还要对存放图片的集合使用weakreference 同时在bitmap使用完毕之后recycle()进行释放 将bitmap占用的像素资源释放
Handler的内存泄露问题
在activity中我们经常会使用handler处理一些事件 经常在代码中会这么写
private Handler handler = new Handler(){
Public void onHandlerMessage(){
}
}
在activity中我们经常这么写 那么此时handler是一个匿名内部类 会持有activity的引用 而伴随着handler的经常是一个耗时操作 例如从网络中获取内容 或者是一个延迟处理的消息 如果是联网获取内容 如果我们在联网的过程中关闭了activity 此时的activity并不能及时的销毁 因为线程并没有执行完毕 而在线程中会持有handler的引用(因为线程在执行完毕之后需要发送消息给handler处理) 而handler又持有activity的引用 此时就会造成内存泄露 同样 如果是一个延时消息的话 handler会在messageQueue中放入一个message等待处理 此时messageQueue会持有looper的引用 looper会持有handler的引用 handler又会持有activity的引用 在message的delay到来之前 activity是不能被销毁的
如果此时频繁的启动销毁该activity 就会OOM
解决方案 可以在activity销毁时停止线程 并且调用handler的removeCallback方法 将消息队列中的消息移出 或者将handler置为static 但是将handler置为static时 handler就不能进行UI的更新操作 那么此时就需要在handler中声明一个activity的weakreference供handler进行使用