前言
前言
由于在Android的UI操作不是线程安全的,所以Android的UI操作必须在主线程中进行(例如在子线程中更新UI时,如果主线程也在对这个UI进行更新操作,就会导致线程不安全),因为Android的主线程不能进行长时间的耗时操作否则产生ANR异常,因此我们要把耗时操作放到子线程中去,当耗时任务完成时,我们要把任务结果反馈给主线程以此来更新UI或者消费耗时任务的“成果”,因此Android引入了Handler机制来帮我们实现主线程和任务线程之间的通讯,以此来规避在子线程中更新UI或者在主线程中进行耗时操作时引发的各种不良后果。
一、Handler是什么?
handler是一种实现主线程、子线程之间的通讯的消息机制。包含 Handler、Loooer、MessageQueue、Message等四部分。
二、Handler工作原理
1.首先要进行的是Looper对象的创建
首先Looper使用了一个静态方法给threadlocal传递了一个值,这个值就是一个Looper对象的实例,在线程中完成绑定。
public static void prepare() {
prepare(true);
}
//创建Looper对象并且与当前线程进行绑定
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//通过ThreadLocal与当前线程进行绑定
sThreadLocal.set(new Looper(quitAllowed));
}
2.创建消息队列
当Looper进行实例化的同时又创建了一个MessageQueue消息队列,通过这个实例化,将Looper和messageQueue绑定在一起,绑定在所创建的当前的线程环境中。
private Looper(boolean quitAllowed) {
//创建了一个消息队列
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
3.小的总结
该首先,在主线程中new Handler()时,实现了如下操作:1、从ThreadLocal中取到了Looper对象;2、从Looper对象中拿到了messageQueue对象的引用。
public Handler(@Nullable Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
mLooper = Looper.myLooper();
//也就是说使用Handler的前提是必须有Looper对象实例
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
//looper又把queue拿过来当作自己的一个成员变量
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
4.Handler发送消息
找到messagequeue对象,将msg的target指向自身。(消息经过handler发送出去后,这个消息反手咬住这个handler自己),最后把msg添加到messagequeue中。
public final boolean sendMessage(@NonNull Message msg) {
return sendMessageDelayed(msg, 0);
}
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
//把接受来的消息添加到了消息池中
return enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
//做好标记,指的是当前的handler对象,发送出来的msg又立刻咬住了当前的handler
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
5.Looper的loop开启死循环进行永动
looper()方法会通过Threadloca拿到Looper对象,从而获得messagequeue对象的引用,然后开启死循环不停的遍历这个消息池,当捕捉到message的时候,就通过msg.target拿到是哪个handler发过来的消息,然后就调用这个Handler的 msg.target.dispatchMessage(msg)方法,进行消息的处理。
public static void loop() {
//从ThreadLocal中拿到Looper对象
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
if (me.mInLoop) {
Slog.w(TAG, "Loop again would have the queued messages be executed"
+ " before this one completed.");
}
me.mInLoop = true;
//把MessageQueue拿到,引用了messageQueue
final MessageQueue queue = me.mQueue;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
// Allow overriding a threshold with a system prop. e.g.
// adb shell 'setprop log.looper.1000.main.slow 1 && stop && start'
final int thresholdOverride =
SystemProperties.getInt("log.looper."
+ Process.myUid() + "."
+ Thread.currentThread().getName()
+ ".slow", 0);
boolean slowDeliveryDetected = false;
//开启死循环,不断的检查消息池中有没有消息
for (;;) {
Message msg = queue.next(); // might block 可能会产生阻塞,但是不会占用太多的CPU资源,会把资源释放
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// .......
//.......
// .......
msg.target.dispatchMessage(msg);
}
}
/**
* Handle system messages here.
*/
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
6.最后在新的线程中具体处理这个message
最后,我们必须在新的线程中(如果是在主线程中new的Handler就是在主线程中,如果是在子线程中new的Handler就是在子线程中)来重写handler中的handleMessage方法,然后对这个message做处理就欧克啦~
639





