消息传递机制的具体实现过程(分析源码之后的总结)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zy_style/article/details/52588986
1,首先得知道有几大类:
    a,Message
    b,Handler
    c,Looper
    d,MessageQueue



2,先创建Message对象和Handler对象.如果Handler是在主线程创建的,那么主线程(也就是ActivityThread,俗称UI线程)会在main方法中默认初始化Looper对(MainLooper)去开启消息循环,类似于Looper.prepare();如果是在子线程创建的,那么需要手动调用Looper.prepare(),并且Looper.loop,因为如果没有创建Looper对象,而是直接new Handler(),底层先判断get()方法能否得到当前线程的Looper,如果没有就会抛异常:Can’t create handler inside thread that has not called Looper.prepare(),所以需要手动调用.调用的过程其实就是底层进行了set()和get()方法,将currentThread(当前进程)的Looper对象和handler对象绑定在一起. 那么 Handler 内部如何获取到当前线程的 Looper 呢? 这就要使用 ThreadLocal 了,ThreadLocal可以在不同的线程中互不干扰地存储并提供数据,通过 ThreadLocal 可以轻松获取每个线程的 Looper。当然需要注意的是,线程是默认没有 Looper 的,如果需要使用 Handler 就必须为线程创建 Looper。所以looper存在于ThreadLocal里面.而looper在什么线程,那么与其绑定的handler处理消息就在什么线程.如果是MainLooper,就能实现更新UI的操作.

3,Looper在创建的时候,构造方法里会初始化MessageQueue,一个Looper对应一个MessageQueue.

4,所有的类初始化完毕,然后handler.sendMessage(msg)发送消息,方法会执行到sendMessageAtTime()这里.此时的msg绑定了when(消息处理的时间),和msg.Target = this(handler将自身的引用绑定在了msg上,是为了在处理多个消息时,能够区分该消息是来自哪个handler),随后通过queue.enqueueMessage()将消息msg放入MessageQueue队列中(利用时间when进行排序,并按先进先出的方式执行,如果没有设置时间,则默认时间为零),虽然叫消息队列,但是它的内部存储结构并不是真正的队列, 而是采用单链表的数据结构来存储消息列表;

5,由于 MessageQueue 只是一个消息的存储单元,它不能去处理消息,而 Looper 就填补了这个功能, Looper 会以无限循环的形式对MessageQueue轮询,去处理消息,如果有消息的话就按顺序依次处理消息,否则就一直等待着(处于阻塞状态);在处理消息的时候,会调用handler的dispatchMessage()方法,最终执行handler.handleMessage(),在该方法里实现处理消息的逻辑(比如更新UI的操作).消息传递就此结束.
展开阅读全文

没有更多推荐了,返回首页