一、Handler
Android规定只能在UI线程中更新UI,并且通过Handler切换到UI线程。
Android系统不允许在子线程中访问UI,因为UI控件不是线程安全的。
Android的消息机制只要是指Handler的运行机制,Handler的运行需要底层的MessageQueue和Looper的支撑。
线程默认是没有Looper的。只是UI线程(主线程),它就是ActivityThread,ActivityThread被创建时就会初始化Looper,这也是在主线程中默认就可以使用Handler的原因。
Handler创建完毕后,其内部的Looper和MessageQueue就可以和Handler一起协同工作,然后通过Handler的post方法将一个Runnable投递到Handler内部的Looper去处理。其实post方法最终也是通过send方法来完成的。
Handler的post方法和handler.sendMessage一样,调用了sendMessageAtTime。
然后调用了enqueueMessage方法,给msg.target赋值为handler,最终加入messagequeue。
这里msg的callback和target都有值,如果callback不为空,先执行callback
当Handler的send方法被调用时,它会调用MessageQueue的enqueueMessage方法将这个消息放入消息队列中,然后Looper发现有新的消息到来时,就会处理这个消息,最终消息中的Runnable或者Handler的handleMessage方法就会被调用。
MessageQueue:消息队列,插入和读取数据。单链表数据结构(查询和删除效率高)。
Looper:负责从消息队列中取消息交给Handler处理
Handler:负责发送和接收消息,消息发送给MessageQueue,Looper取到再交给Handler处理。
Handler中的关键方法:sendMessageAtTime发送消息最终执行的方法和dispatchMessage接收消息的方法
Handler中的延迟消息原理,MessageQueue中的next方法中,SystemClock.uptimeMillis()获取时间,用这个时间和消息中的时间对比,在next方法中naticePollOnce进入休眠,时间到会自动唤醒。
二、ThreadLocal
ThrealLocal是一个线程内部的数据存储类,通过它可以在指定的线程中存储数据。
一般来说,当某些数据是以线程为作用域并且不同线程具有不同的数据副本的时候,就可以使用ThreadLocal。
ThreadLocal的reference对象在table数组中的索引为index,那么ThreadLocal的值在table数组中的索引就是index+1;
其内部实现,
ThreadLocal是一个线程内部的数据存储类,线程之间互不影响。
ThreadLocal中有set和get方法,其中ThreadLocalMap用于存储当前线程的副本。
是通过Entry数组,通过key的hashcode来计算存储索引位置。
三、消息队列的工作原理
消息队列在Android中指的是MessageQueue,MessageQueue主要包含两个操作:插入和读取。
读取操作本身会伴随删除操作。
插入:enqueueMessage;读取:next
消息队列,实际上它是通过一个单链表的数据结构来维护消息列表,因为单链表在插入和删除上比较有优势。
四、Looper的工作原理
Looper的具体实现。Looper在Android的消息机制中扮演着消息循环的角色,它会不停地从MessageQueue中查看是否有新消息,如果有新消息就会立即处理,否则就一直阻塞在那里。
为什么Looper.loop()死循环不会导致ANR:
Looper.loop()方法可能引起主线程的阻塞,但只要它的消息循环没有被阻塞,能一直处理事件就不会产生ANR异常。
Looper中的prepare()方法的作用是为当前线程创建Looper
Looper中的loop()方法的作用是开启消息循环
退出Looper的两个方法:
quit和quitSafely
quit会直接退出looper,而quitSafely会等消息队列中的已有消息处理完毕后才会安全退出Looper。