Handler源码分析

Handler整体架构

  1. handler能做什么?

 1. 推送未来某个时间点将要执行的Message或者Runnable到消息队列 (处理延时任务) 
 
 2. 在子线程需要在
    另一个线程执行的操作加入到消息队列中去 (线程间通信)

  1. 源码分析

 - 首先从Handler.sendmessage()出发发现最后调用MessageQueue.enqueueMessage(),实现添加message


 - 然后thread---->Looper.loop()----->MessageQueue.next()拿出消息,销毁队列里面的消息

Handler源码分析Handler源码分析
Handler源码分析

MessageQueue.enqueueMessage()

Handler源码分析

MessagQueue.next()

Handler源码分析

  • next是被loop()调用的
  • Looper.loop()
    Handler源码分析
  • loop()由Looper调用
  • Looper被谁调用?
每一个应用都是一个单独的实体 ,有一个在 ActivityThread里面main函数调用looper.prepareMainLooper()对应Looper的创建函数,之后调用Looper.loop(),   而prepareMainLooper中的prepare来调用过 

ActivityThread

Handler源码分析

Looper

Handler源码分析

ThreadLocal线程隔离工具:保证只有一个Looper

  • ThreadLocal 利用set get方法实现类似hashmap结构
  • key是ThreadId(虚拟机分配,独一无二), value存的是Looper对象,里面每一个数组保存的节点都是<key, value>对象

Handler源码分析
Handler源码分析

为什么使用ThreadLocal不用HashMap

Hashmap太臃肿,因为此处的key就一种类型

如何保证Looper的唯一性

looper.myLooper()获取Looper对应线程对应唯一的looper  ---> looper.mQueue 获取looper获取唯一关联的mQueue 

MessageQueue的数据结构:

使用的是生产者消费者模型,向同一块内存(MessageQueue)中写入消息  

 1.入队时如果队列满则阻塞,直到调用next()方法取出消息,可以进行入队操作
 2.出队时如果队列为空则阻塞,直到调用enqueueMessage(),通知队列可以取出消息