源码解析 Handler机制
程序员文章站
2022-07-14 16:46:22
...
系统为什么不允许在子线程里访问UI?那是因为Android的UI控件线程不安全,如果多线程并发访问的话会导致UI控件处于不可预期的状态。
ThreadLocal 工作原理
ThreadLocal是一个线程内部的储存类,通过它可以在指定的线程中存储数据,数据储存以后,只有在指定线程中可以获取到存储的数据,对于其他线程来说则无法获取到数据。
Handler机制 四种主体类
- Lopper:消息轮训器
- MessageQueue:消息队列
- Handler:处理消息
- Message:消息对象
开启应用时
- 1) ActivityThread.java
当应用启动时,会调用ActivityThread的main方法,在main方法里调用prepareMainLooper()方法和loop()方法
// ActivityThread.java
public static void main(String[] args) {
Looper.prepareMainLooper();
........
Looper.loop();
}
- 2)Looper.java
#1 在prepare()方法里回去获取当前的Looper,如果没有的话(启动应用时是没有的)会走下面sThreadLocal.set(new Looper(quitAllowed)),在Looper的初始化操作中会初始化MessageQueue,并且绑定当前线程(当前即为ui线程);
#2 在loop()方法里会去获取当前Looper,并获取MessageQueue的实例,如果为null的话会有异常报出,然后遍历mQueue去拿到Message的引用msg,调用dispatchMessage(msg)(其实就是handler的dispatchMessage(msg))
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
// prepareMainLooper() =>
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
// Looper构造
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
// loop()
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
....
for (;;) {
Message msg = queue.next(); // might block
//这里的msg.target指的就是handler
msg.target.dispatchMessage(msg);
msg.recycle();
}
}
初始化Handler
- 1)MainActivity.java
Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandler.sendEmptyMessageAtTime(1,1000);
}
- 2 )Handler.java
#1 在handler初始化方法里获取looper对象,通过looper对象回去mQueue,在mHandler.sendEmptyMessage()时,通过msg.target = this将当前handler绑定到message中,再通过获取到的mQueue.enqueueMessage()将当前message传入mQueue中
public Handler() {
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
}
// => sendEmptyMessageAtTime
public boolean sendMessageAtTime(Message msg, long uptimeMillis){
boolean sent = false;
MessageQueue queue = mQueue;
if (queue != null) {
//这里其实就是把handler赋值给message.target
msg.target = this;
sent = queue.enqueueMessage(msg, uptimeMillis);
} else {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
}
return sent;
}
// msg.target.dispatchMessage(msg); 接上边的looper
// handleMessage(msg) 创建handler时,复用的方法
public void handleMessage(Message msg) {
}
备注:handler机制的一些参考
转载于:https://www.jianshu.com/p/665c23fb9fbf
上一篇: Handler 流程源码解析
下一篇: Handler、Looper源码学习
推荐阅读