深入剖析 Handler(二):API 及内存泄漏问题
2023-12-30 01:35:15
相关API
如果我们想创建工作线程时,其实并不需要在新建线程的时候创建handler,因为系统会为每个线程创建一个looper,只要获取当前线程的looper就能操作handler了。常用的api函数有:
MessageQueue.next():取出消息队列中的消息。
Message.obtain(Handler,Runnable):获得一个runnable消息。
Message.obtain(Handler,int,Object):获得一个int值消息。
Message.obtain(Handler,int,int,Object):获得一个带两个int值的消息。
Message.sendToTarget():把消息发送到目标handler。
Message.getTarget():获得消息的目标handler。
Handler.dispatchMessage(Message):处理消息。
Handler.sendMessage(Message):发送消息。
Handler.sendMessageDelayed(Message,long):延迟发送消息。
Handler.removeMessages(int):移除消息。
Handler.postDelayed(Runnable,long):延迟执行runnable。
内存泄漏
虽然handler是一个很强大的工具,但是handler与activity有很大的关系,需要在activity创建和销毁的时候进行一些处理,否则会产生内存泄漏。这是因为handler的内部类callback会持有外部类activity的引用,即使activity已经被销毁了,但是callback对象中依然持有这个activity的引用,这就导致了内存泄漏。
解决这个问题有两种方法,一种是把activity的引用设置为weakReference,这样当activity被销毁后,弱引用自动会变成null,从而解决内存泄漏。
另一种方法是使用静态内部类,这种方法同样不会持有外部类的引用,同样可以解决内存泄漏的问题。但是对于一些大型的项目,每个activity都有多个handler的话,势必要创建很多静态内部类,这样会非常混乱。
因此,最佳的方法还是使用弱引用,但是需要注意弱引用在GC的时候会变成null,可能造成一些错误,所以需要自己做一些判断。
相关 API
1. MessageQueue.next()
- 作用:取出消息队列中的消息。
2. Message.obtain(Handler, Runnable)
- 作用:获得一个 Runnable 消息。
3. Message.obtain(Handler, int, Object)
- 作用:获得一个 int 值消息。
4. Message.obtain(Handler, int, int, Object)
- 作用:获得一个带两个 int 值的消息。
5. Message.sendToTarget()
- 作用:把消息发送到目标 Handler。
6. Message.getTarget()
- 作用:获得消息的目标 Handler。
7. Handler.dispatchMessage(Message)
- 作用:处理消息。
8. Handler.sendMessage(Message)
- 作用:发送消息。
9. Handler.sendMessageDelayed(Message, long)
- 作用:延迟发送消息。
10. Handler.removeMessages(int)
- 作用:移除消息。
11. Handler.postDelayed(Runnable, long)
- 作用:延迟执行 Runnable。
内存泄漏
1. 问题
- Handler 与 Activity 有很大的关系,需要在 Activity 创建和销毁的时候进行一些处理,否则会产生内存泄漏。这是因为 Handler 的内部类 Callback 会持有外部类 Activity 的引用,即使 Activity 已经被销毁了,但是 Callback 对象中依然持有这个 Activity 的引用,这就导致了内存泄漏。
2. 解决方法
- 解决这个问题有两种方法:
- 使用弱引用(WeakReference)
- 使用静态内部类(Static Inner Class)