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