Handler允许发送和处理与线程的MessageQueue相关联Message和Runnable对象。每一个Handler实例都与一个单独的线程和该线程的消息队列相关联。当创建Handler的时候,它被它创建的线程绑定。它把Message或Runnable对象传递到消息队列,出队的时候执行它们。Handler有两个主要用处:1.调度消息和Runnable在未来的某个时间点执行。2.入队一个操作并在不同的线程上执行。
调度消息通过post,postAtTime(Runnable,long),postDelayed,sendEmptyMessage,sendMessage,sendMessageAtTime,sendMessageDelayed方法完成。post版本允许入队Runnable对象,sendMessage版本允许入队Message对象,Message对象包含的数据会被Handler的handleMessage方法处理(需要自己实现Handler的子类)。
post或send的时候可以允许item在消息队列准备好的时候立即处理,或者定义一个时间延迟或确切的时间处理。
当一个应用的进程创建完,它的主线程专注运行一个消息队列,负责管理高级别的应用对象(Activity,BroadcastReceiver等)和他们创建的window,我们可以创建自己的子线程,并通过Handler和主线程通信。这样是通过在子线程里调用post或sendMessage方法完成。然后Runnable或Message将在Handler的消息队列里调度,在合适的时候处理。
Handler总共有7个构造函数
#无参构造函数,内部调用6,callback传null,async传false
1. public Handler() {
this(null, false);
}
#设置消息处理回调,内部调用6,async传false
2. public Handler(@Nullable Callback callback) {
this(callback, false);
}
#设置Looper,这样就不用调用Looper.prepare方法,内部调用7
3. public Handler(@NonNull Looper looper) {
this(looper, null, false);
}
#设置Looper和回调,内部调用7
4. public Handler(@NonNull Looper looper, @Nullable Callback callback) {
this(looper, callback, false);
}
#设置消息是否异步,内部调用6
5. public Handler(boolean async) {
this(null, async);
}
#设置回调和是否异步,内部检测looper是否为空,所以所有内部调用这个方法的构造函数都需要先调用Looper.prepare方法初始化Looper和MessageQueue
6. 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();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
#设置Looper,回调,是否异步
7. public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}Handler总共有7个构造函数,分别应用在不同场景下,可以设置消息是否异步,设置Looper,回调。
消息处理使用dispatchMessage方法,在Looper的loop中,获取到Message以后,通过msg.target.dispatchMessage
private static void handleCallback(Message message) {
message.callback.run();
}
public void handleMessage(@NonNull Message msg) {
}
/**
* Handle system messages here.
*/
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) { //优先处理Message的callback
handleCallback(msg);
} else {
if (mCallback != null) { //其次处理Handler的Callback对象
if (mCallback.handleMessage(msg)) {
return;
}
}
//msg.callback和Handler的Callback对象都是空的,走Handler的handleMessage方法
handleMessage(msg);
}
}msg.callback>Handler的mCallback>Handler的handleMessage方法。msg.callback可以在构造Message的时候设置,mCallback可以在上述构造函数中2,4,6,7中设置,handleMessage方法可以在我们继承Handler的时候重写该方法。
文章开头讲过,发送消息主要有两个版本,post和send。post版本会传递一个Runnable对象,封装成Message的callback,然后加入消息队列,这样post版本会在dispatchMessage的时候,优先执行msg.callback。send版本会直接传递一个Message对象。
不论是post版本还是send版本,都会调用Handler的sendMesssageAtTime
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) {
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}Handler移除消息的方法主要有三种removeCallback,removeMessages和removeCallbackAndMessages
removeCallback有两个方法,内部都调用了MessageQueue的removeMessages(Handler h, Runnable r, Object object)
#移除消息队列里post的Runnbale对象是r的Message
public final void removeCallbacks(@NonNull Runnable r) {
mQueue.removeMessages(this, r, null);
}
#移除消息队列里post的Runnable对象是r且obj是token的Message,如果token是null,则移除Runnable对象是r的Message
public final void removeCallbacks(@NonNull Runnable r, @Nullable Object token) {
mQueue.removeMessages(this, r, token);
}
#MessageQueue的方法
void removeMessages(Handler h, Runnable r, Object object) {
if (h == null || r == null) {
return;
}
synchronized (this) {
Message p = mMessages;
// Remove all messages at front.
#从队首Message开始查找Message的target是h,且callback是r,且object是空或obj等于object的Message对象,
找到了就移除并回收该Message,p指向下一个节点
while (p != null && p.target == h && p.callback == r
&& (object == null || p.obj == object)) {
Message n = p.next;
mMessages = n;
p.recycleUnchecked();
p = n;
}
// Remove all messages after front.
#经过上面的循环,如果p不是空,则获取p的下个节点,依然做上述条件查找Message对象,找到了就回收该Message,p的下个节点指向回收对象的下个节点,并继续查找,如果找不到则p指向下个节点,继续循环查找,直到p是null
while (p != null) {
Message n = p.next;
if (n != null) {
if (n.target == h && n.callback == r
&& (object == null || n.obj == object)) {
Message nn = n.next;
n.recycleUnchecked();
p.next = nn;
continue;
}
}
p = n;
}
}
}removeMessages方法有两个,内部调用了MessageQueue的removeMessages(Handler h, int what, Object object)
#移除消息队列里Message.what是what的消息
public final void removeMessages(int what) {
mQueue.removeMessages(this, what, null);
}
#移除消息队列里Message.what,Message.obj是object的消息,如果object是null,则移除消息队列Message.what是what的消息
public final void removeMessages(int what, @Nullable Object object) {
mQueue.removeMessages(this, what, object);
}
void removeMessages(Handler h, int what, Object object) {
if (h == null) {
return;
}
synchronized (this) {
Message p = mMessages;
// Remove all messages at front.
#从队首Message开始查找Message的target是h,且what是what,且object是空或obj等于object的Message对象,
找到了就移除并回收该Message,p指向下一个节点
while (p != null && p.target == h && p.what == what
&& (object == null || p.obj == object)) {
Message n = p.next;
mMessages = n;
p.recycleUnchecked();
p = n;
}
// Remove all messages after front.
#经过上面的循环,如果p不是空,则获取p的下个节点,依然做上述条件查找Message对象,找到了就回收该Message,p的下个节点指向回收对象的下个节点,并继续查找,如果找不到则p指向下个节点,继续循环查找,直到p是null
while (p != null) {
Message n = p.next;
if (n != null) {
if (n.target == h && n.what == what
&& (object == null || n.obj == object)) {
Message nn = n.next;
n.recycleUnchecked();
p.next = nn;
continue;
}
}
p = n;
}
}
}public static void main(String[] args){
.....
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
.....
Looper.loop();
} final H mH = new H();
final Handler getHandler() {
return mH;
}H类是ActivityThread的内部类,主要用来处理系统消息比如应用的绑定和退出,Activity打开和生命周期,Service的创建停止等。
主线程的Handler创建的时候,ActivityThread的main方法里自动帮我们调用了Looper.prepareMainLooper和Looper.loop方法,而我们在子线程创建Handler的时候,首先要调用Looper .prepare方法创建looper对象和MessageQueue对象,再创建Handler对象,再调用Looper.loop开启消息循环,否则Hanlder实例化的时候会直接抛出异常。
HandlerThread继承自Thread,内部持有Looper和Handler实例,在run方法里自动调用Looper.prepare方法和Looper.loop方法自动准备好消息队列和循环,使用HanlderThread能够简化在子线程创建Hanlder。免去调用Looper.prepare和Looper.loop方法。
Handler机制是安卓消息循环机制的基石,Handler是Handler机制的指挥者
Handler发送消息方式有两个版本,post和send,post版本发送一个runnable对象,send直接发送Message对象,post和send最终都调用了MessageQueue的enqueueMessage方法。
Handler处理消息的方法是dispatchMessge方法,优先处理msg.callback,其次是Handler的mCallback对象,最后才是handleMessage方法。
Handler移除消息的方法最终都是调用MessageQueue的移除方法。
本文为Adamin90原创文章,转载无需和我联系,但请注明来自http://www.lixiaopeng.top
