# LeakCanary傻瓜式的内存泄露检测工具
在开发`Android`应用的过程中如果需要处理图片或者大量数据的时候,就有可能会遇到**OOM**(`java.lang.OutOfMemoryError`),一般出现最多的是在创建`Bitmap`上,也有可能是在内存中处理了大量的数据上。出现**OOM**应用会直接崩溃,即使没有出现**OOM**,内存使用过大的时候应用也会出现卡顿。所以内存的优化在开发Android应用时是一个比较重要的任务。
一般会针对`Bitamp`的内存优化有下面几种方式:
1. 增加进程的内存
2. 使用Bitmap.Config.ALPHA_8(图片失真)
3. 显示的调用System.gc()
4. catch Exception
5. 调用bitmap.recycle()
6. 缩小bitmap的大小(如果是读取的原图是一个大图应该先采用这种方式,Bitmap如果是刚好适配屏幕的就不需要缩小了)
7. 使用弱引用和软引用(google已经不建议使用了,Android的GC效率非常高,只要保证对象没有被引用即可)
但是我们忽略掉一个问题就是什么造成了**OOM**?
一般来说发生**OOM**崩溃的地方不一定是内存泄露的地方,崩溃的原因有可能是`Activity`造成的内存泄露,也可能是操作数据库造成的内存泄露,当内存已经非常接近峰值的时候,这个时候恰巧要创建一个`Bitmap`对象就会发生`OOM`(Bitmap对象占用的内存比较大)。
是什么原因造成了内存泄露呢?
## 内存泄露
我们知道Android中每个对象都有自己的生命周期,比如`Activity`的生命周期最后会调用`onDestroy`方法做销毁处理,但如果使用`Activity`中调用了类似于`Toast`这种对象,就会把这个`Activity`的引用传给了`Toast`,而`Toast`的生命周期不会随着`Activity`的销毁而销毁,这样就造成了`Activity`的内存泄露,它会被`Toast`对象引用,无法被销毁。
常见的内存泄露形成的原因:
* Toast持有Activity的引用
* 数据库游标Cursor没有关闭
* Adapter没有复用convertView
* 对象被生命周期更长的对象引用,Activity被静态集合引用
* ....
那如何知道应用的内存有没有出现泄露呢?
## 监控内存的方式
`Heap Dump`:常见的内存监控方式是`Heap Dump`,`Heap Dump`是一