首先看图

Android 中 handler 使用handle android handler looper_main函数


应用启动时的入口是ActivityThread的main函数,即是Java的启动入口main函数。在这个main函数中会创建主线程的Looper,之后在主线程中创建的Handler使用的消息机制都执行于main函数的Looper中,其实其他代码也都是执行在loop中的。Looper.loop()有一个for的死循环不断读取消息进行处理,而mMainLooper是不能调用Looper.quit()或Looper.quitSafely()函数的,所以mMainLooper会不停的读取消息链表的消息然后处理,如果有某种消息处理时间过长就会导致卡顿、ANR等。

消息传递流程

首先是创建Handler,而Handler主要的方法就是sendMessage,它用于将消息保存入队列,等待loop中读取再执行。

消息的实体是Message,它有一个next属性,这是组成链表的结构,属性when表示消息执行时间,由参数delayMillis决定,但因为Handler可以在多线程中执行,所以为了保证多线程执行的唯一性,使用了synchronized进行加锁处理,保证在消息入队列和消息出队列时的唯一性,when只保证了消息的执行顺序,不保证执行时间。

Message.target的类型是Handler,这也是保证消息处理后能原路返回结果,但是这个的存在同时也存在内存泄漏的风险。内存泄漏是因为内部类保持了外部类的引用,导致外部类无法释放。那么使用Handler的时候就需要注意这个了,首先需要清空Message才能释放掉Handler,从而再释放Activity等。也有的解决方法是创建特殊的Handler。

将消息保存到队列是MessageQueue的功能,但其实是Message的结构决定的,根据参数when决定消息压入队列链表的某个位置。

Android 中 handler 使用handle android handler looper_链表_02

Looper.loop死循环遍历消息队列,假如队列是空queue.next()会进行休眠等待,直到下个消息的到来。

Android 中 handler 使用handle android handler looper_handler_03


主线程的Looper是不能quit的,但是子线程的Looper是可以quit的,也为了节省资源,可以看到它会调用MessageQueue的quit方法将消息队列清空并唤醒Looper,让Looper.loop的死循环的queue.next()返回一个null,从而结束死循环,这样才算是完全释放这个Looper,否则Looper会一直休眠等待。

Android 中 handler 使用handle android handler looper_链表_04


Android 中 handler 使用handle android handler looper_handler_05