1.Handler 引起的内存泄漏
Handler是Andorid给我们提供的一套UI更新机制,同时它也是一套消息处理机制。
使用Handler消息处理机制在多个线程并发更新UI的同时 ,可以保证线程安全。
先看看下图:
出现了一大片黄色警告,what?怎么回事的。黄色警告的大概意思:Handler可能会内存泄漏,推荐使用静态内部类+实例化弱引用。在使用Handler时如果直接使用匿名内部类的方式创建Handler对象IDE会发出警告,提示内存泄漏风险。非静态的内部类和匿名类会隐式地持有一个他们外部类的引用。静态内部类则不会。
上图的Handler正是通过内部类创建的,它可能会阻止外部类被垃圾收集(假如上图的程序代码是在Activity类里创建的,就算关闭了Activity,Activity还是无法被回收的)。
如果程序代码对主线程以外的线程使用循环程序或MessageQueue,就没什么问题。但是如果程序代码使用到了主线程的Looper或MessageQueue,则很可能会导致内存泄漏。有以下解决方案:
方法一:
添加这个 @SuppressLint("HandlerLeak")注解,防止由handler引起的内存溢出,此时黄色警告就没有了。
方法二:
在实例化Handler时可以使用回调接口,以避免必须实现自己的Handler子类。如下图:
方法三:
使用静态内部类+实例化弱引用
(ps: Handler可以发送和处理消息对象或Runnable对象,这些消息对象和Runnable对象与一个线程相关联。每个Handler的实例都关联了一个线程和线程的消息队列。当创建了一个Handler对象时,一个线程或消息队列同时也被创建,该Handler对象将发送和处理这些消息或Runnable对象。)
2.Handler与线程相关的图解
3.除了Handler引起的内存泄漏,以下常见操作也会引起内存泄漏:
3.1 IO操作没有关流以及Cursor游标的一些操作,忘记关掉Cusor;
3.2 Bitmap对象没有recycle()释放内存;
3.3 发送广播、定义广播接收者时没有反注册,以及EventBus的反注册;
3.4 接口回调时界面间持有引用,关闭不完全很可能引起的内存泄漏;
比如,网络请求使用Activity当做回调,如果网速慢,设置了30秒才会链接超时,此时按下返回键,Activity会被网络请求给引用大约30秒然后才有可能被释放。
3.5 单例模式导致内存泄漏(实质是静态变量引用Activity),由于它的静态特性使得其生命周期跟应用一样长,如果我们把上下文Context(比如说一个Activity)传入到了单例类中的执行业务逻辑,这时候静态变量就引用了我们的Activity,如果没有及时置空,就会在这个Activity finish的时候,导致该Activty一直驻留在内存中,并发生内存泄漏,所以传入上下文对象时应Application的Context来替代和Activity相关的Context;
3.6 bindService绑定服务后,没有unbindService解绑服务,会导致ServiceConnection 泄露。