一说到Android的消息机制,自然就会联想到Handler,我们知道Handler是Android消息机制的上层接口,因此我们在开发过程中也只需要和Handler交互即可,很多人认为Handler的作用就是更新UI,这也确实没错,但除了更新UI,Handler其实还有很多其他用途,比如我们需要在子线程进行耗时的I/O操作,可能是读取某些文件或者去访问网络等,当耗时操作完成后我们可能需要在UI上做出相应的改变,但由于Android系统的限制,我们是不能在子线程更新UI控件的,否则就会报异常,这个时候Handler就可以派上用场了,我们可以通过Handler切换到主线程中执行UI更新操作。
1.Handler和Looper
当Handler实例化的时候,Looper会自动关联Handler所在线程,如果Looper什么都不设置,默认关联的就是主线程2.Looper和MessageQueue
当Looper实例化的时候,内部会初始化MessageQueue消息队列,消息队列如果和主线程关联,是打开的;如果不是主线程,要自己操作(消息队列打开就能接受消息,不打开就不接受消息)。
有专门控制的标志变量
3.Handler和Message
可以对Message操作,发送,删除
4.Handler和MessageQueue
Handler发送的消息由MessageQueue统一处理,MessageQueue通过回调方法可以确认该消息已经处理过了
是通过回调接口用的回调方法
5.Message和MessageQueue
MessageQueue里面存放Message
下面是Handler一些常用方法:
void handleMessage(Message msg):处理消息的方法,该方法通常会被重写。
final boolean hasMessages(int what):检测消息队列中是否包含what属性为指定值的消息。
Message obtainMessage():获取消息的方法,此函数有多个重载方法。
sendEmptyMessage(int what):发送空消息。
final boolean sendEmptyMessageDelayed(int what , long delayMillis):指定多少毫秒后发送空消息。
final boolean sendMessage(Message msg):立即发送消息。
final boolean sendMessageDelayed(Message msg ,long delayMillis):指定多少毫秒后发送消息。
final boolean post(Runnable r):执行runnable操作。
final boolean postAtTime(Runnable r, long upTimeMillis):在指定时间执行runnable操作。
final boolean postDelayed(Runnable r, long delayMillis):指定多少毫秒后执行runnable操作。
介绍完方法后,我们就从一个简单的例子入手吧,然后一步步的分析:
- public class MainActivity extends AppCompatActivity {
- public static final int MSG_FINISH = 0X001;
- //创建一个Handler的匿名内部类
- private Handler handler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_FINISH:
- LogUtils.e("handler所在的线程id是-->" + Thread.currentThread().getName());
- break;
- }
- }
- };
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- //启动耗时操作
- consumeTimeThread(findViewById(R.id.tv));
- // handler.post()
- }
- //启动一个耗时线程
- public void consumeTimeThread(View view) {
- new Thread() {
- public void run() {
- try {
- LogUtils.e("耗时子线程的Name是--->" + Thread.currentThread().getName());
- //在子线程运行
- Thread.sleep(2000);
- //完成后,发送下载完成消息
- handler.sendEmptyMessage(MSG_FINISH);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }.start();
- }
- }
上面的例子其实就是Handler的基本使用,在主线中创建了一个Handler对象,然后通过在子线程中模拟一个耗时操作完成后通过sendEmptyMessage(int)方法发送一个消息通知主线程的Handler去执行相应的操作。通过运行结果我们也可以知道Handler确实也是在主线程运行的。
那么问题来了,通过Handler发送的消息是怎么到达主线程的呢?接下来我们就来掰掰其中的奥妙,前方高能,请集中注意力!为了更好的理解Handler的工作原理,我们先来介绍与Handler一起工作的几个组件:
Message:Handler接收和处理消息的对象。
Looper:每个线程只能有一个Looper。它的loop方法负责读取MessageQueue中的消息,读到消息后把消息发送给Handler进行处理。
MessageQueue:消息队列,它采用先进先出的方式来管理Message。程序创建Looper对象时,会在它的构造方法中创建MessageQueue对象。
Handler:它的作用有两个—发送消息和处理消息,程序使用Handler发送消息,由Handler发送的消息必须被送到指定的MessageQueue;否则消息就没有在MessageQueue进行保存了。而MessageQueue是由Looper负责管理的,也就是说,如果希望Handler正常工作的话,就必须在当前线程中有一个Looper对象。我们先对上面的几个组件有大概的了解就好,后面我们都会详细分析,既然消息是从Handler发送出去,那么我们就先从Handler入手吧。先来看看Handler 的构造方法源码:
- public class Handler {
- /**
- * 未实现的空方法handleMessage()
- */
- public void handleMessage(Message msg) {
- }
- /**
- * 我们通常用于创建Handler的构造方法之一
- */
- public Handler() {
- this(null, false);
- }
- // 构造方法的内调用的this(null, false)的具体实现
- public Handler(Callback callback, boolean async) {
- //检查Handler是否是static的,如果不是的,那么有可能导致内存泄露
- 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());
- }
- }
- //重要的组件出现啦!Looper我们先理解成一个消息队列的管理者,用来从消息队列中取消息的,后续会详细分析
- mLooper = Looper.myLooper();
- if (mLooper == null) {
- //这个异常很熟悉吧,Handler是必须在有Looper的线程上执行,这个也就是为什么我在HandlerThread中初始化Handler
- //而没有在Thread里面初始化,如果在Thread里面初始化需要先调用Looper.prepare方法
- throw new RuntimeException(
- "Can't create handler inside thread that has not called Looper.prepare()");
- }
- //将mLooper里面的消息队列复制到自身的mQueue,这也就意味着Handler和Looper是公用一个消息队列
- mQueue = mLooper.mQueue;
- //回调函数默认是Null
- mCallback = null;
- }
- if (mLooper == null) {
- //这个异常很熟悉吧,Handler是必须在有Looper的线程上执行,这个也就是为什么我在HandlerThread中初始化Handler
- //而没有在Thread里面初始化,如果在Thread里面初始化需要先调用Looper.prepare方法
- throw new RuntimeException(
- "Can't create handler inside thread that has not called Looper.prepare()");
- } </span>
(1)在主UI线程中,系统已经初始化好了一个Looper对象,因此我们可以直接创建Handler并使用即可。
(2)在子线程中,我们就必须自己手动去创建一个Looper对象,并且去启动它,才可以使用Handler进行消息发送与处理。使用事例如下:
- class childThread extends Thread{
- public Handler mHandler;
- @Override
- public void run() {
- //子线程中必须先创建Looper
- Looper.prepare();
- mHandler =new Handler(){
- @Override
- public void handleMessage(Message msg) {
- super.handleMessage(msg);
- //处理消息
- }
- };
- //启动looper循环
- Looper.loop();
- }
- }
- // 发送一个空消息的方法,实际上添加到MessagerQueue队列中
- public final boolean sendEmptyMessage(int what) {
- return sendEmptyMessageDelayed(what, 0);
- }
- // 给上一个方法调用
- public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
- Message msg = Message.obtain();
- msg.what = what;
- return sendMessageDelayed(msg, delayMillis);
- }
- // 给上一个方法调用
- public final boolean sendMessageDelayed(Message msg, long delayMillis) {
- if (delayMillis < 0) {
- delayMillis = 0;
- }
- return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
- }
- // 给上一个方法调用
- public boolean sendMessageAtTime(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(MessageQueue queue, Message msg,
- long uptimeMillis) {
- msg.target = this;// 设置发送目标对象是Handler本身
- if (mAsynchronous) {
- msg.setAsynchronous(true);
- }
- return queue.enqueueMessage(msg, uptimeMillis);// 添加到消息队列中
- }
- // 在looper类中的loop()方法内部调用的方法
- public void dispatchMessage(Message msg) {
- if (msg.callback != null) {
- handleCallback(msg);
- } else {
- if (mCallback != null) {
- if (mCallback.handleMessage(msg)) {
- return;
- }
- }
- handleMessage(msg);
- }
- }
- public final class Looper {
- // sThreadLocal.get() will return null unless you've called prepare().
- //存放线程的容器类,为确保获取的线程和原来的一样
- static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
- private static Looper sMainLooper; // guarded by Looper.class
- //消息队列
- final MessageQueue mQueue;
- final Thread mThread;
- //perpare()方法,用来初始化一个Looper对象
- public static void prepare() {
- prepare(true);
- }
- 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));
- }
- //handler调用的获取Looper对象的方法。实际是在ThreadLocal中获取。
- public static Looper myLooper() {
- return sThreadLocal.get();
- }
- //Looper类的构造方法,可以发现创建Looper的同时也创建了消息队列MessageQueue对象
- private Looper(boolean quitAllowed) {
- mQueue = new MessageQueue(quitAllowed);
- mRun = true;
- mThread = Thread.currentThread();
- }
- //这个方法是给系统调用的,UI线程通过调用这个线程,从而保证UI线程里有一个Looper
- //需要注意:如果一个线程是UI线程,那么myLooper和getMainLooper是同一个Looper
- public static final void prepareMainLooper() {
- prepare();
- setMainLooper(myLooper());
- if (Process.supportsProcesses()) {
- myLooper().mQueue.mQuitAllowed = false;
- }
- }
- //获得UI线程的Looper,通常我们想Hanlder的handleMessage在UI线程执行时通常会new Handler(getMainLooper());
- public synchronized static final Looper getMainLooper() {
- return mMainLooper;
- }
- //looper中最重要的方法loop(),该方法是个死循环,会不断去消息队列MessageQueue中获取消息,然后调dispatchMessage(msg)方法去执行
- 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
- if (msg == null) {
- // No message indicates that the message queue is quitting.
- return;
- }
- //这里其实就是调用handler中的方法,而在Handler的源码中也可以知道dispatchMessage(msg)内部调用的就是handlerMessage()方法
- msg.target.dispatchMessage(msg);
- msg.recycle();
- }
- }
- //perpare()方法,用来初始化一个Looper对象
- public static void prepare() {
- prepare(true);
- }
- 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类的构造方法,可以发现创建Looper的同时也创建了消息队列MessageQueue对象
- private Looper(boolean quitAllowed) {
- mQueue = new MessageQueue(quitAllowed);
- mRun = true;
- mThread = Thread.currentThread();
- }
- //handler调用的获取Looper对象的方法。实际是在ThreadLocal中获取。
- public static Looper myLooper() {
- return sThreadLocal.get();
- }
- //looper中最重要的方法loop(),该方法是个死循环,
- //会不断去消息队列MessageQueue中获取消息,
- //然后调dispatchMessage(msg)方法去执行
- 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
- if (msg == null) {
- // No message indicates that the message queue is quitting.
- return;
- }
- //这里其实就是调用handler中的方法,而在Handler的源码中也可以知道dispatchMessage(msg)内部调用的就是handlerMessage()方法
- msg.target.dispatchMessage(msg);
- msg.recycle();
- }
- // 在looper类中的loop()方法内部调用的方法
- public void dispatchMessage(Message msg) {
- if (msg.callback != null) {
- handleCallback(msg);
- } else {
- if (mCallback != null) {
- if (mCallback.handleMessage(msg)) {
- return;
- }
- }
- handleMessage(msg);
- }
- public final boolean post(Runnable r)
- {
- return sendMessageDelayed(getPostMessage(r), 0);
- }
- private static Message getPostMessage(Runnable r) {
- Message m = Message.obtain();
- m.callback = r;
- return m;
- }
- private static void handleCallback(Message message) {
- message.callback.run();
- }
- /**
- * Callback interface you can use when instantiating a Handler to avoid
- * having to implement your own subclass of Handler.
- *
- * @param msg A {@link android.os.Message Message} object
- * @return True if no further handling is desired
- */
- public interface Callback {
- public boolean handleMessage(Message msg);
- }
这个接口有什么用呢?其实通过Callback接口我们就可以采取如下方法来创建Handler对象:
- Handler handler =new Handler(callback)
最后我们来个小总结:Android中的Looper类主要作用是来封装消息循环和消息队列的,用于在android线程中进行消息处理。handler是用来向消息队列中插入消息的并最好对消息进行处理。
看了不少关于Handler、Looper、MessageQueue之间关系的文章。感觉挺枯燥的,上来就是一团代码,看着心烦。
总结: 后来我捋了捋,画了个图。先看图,我们再来谈他们间的关系:
在这个图中,我做了个类比:(很重要,多看几遍)
MessageQueue,流水线上的"履带";
Looper,履带的"驱动轮";
Handler,流水线上的"工人";
Message,流水线上的"包裹"。
现在让我们来解释这三者间的工作关系,首先,我们要明确一个基本法:
一个Thread只能有且只能一个Looper。一个Looper只能对应一个Message。一个Looper和MessageQueue的绑定体可以对应多个Handler。(参考上图)
1.Looper与MessageQueue
刚刚说了一个Thread只能有一个Looper。为什么只能有一个呢?让我们去看它的一个方法Looper.prepare()方法的源码:
- public static final void prepare() {
- if (sThreadLocal.get() != null) {
- throw new RuntimeException("Only one Looper may be created per thread");
- }
- sThreadLocal.set(new Looper(true));
- }
然后我们再来说说一个线程一般要怎么创建一个Looper,例子A:(下面会拿这个例子讲解)
- class LooperThread extends Thread {
- public Handler mHandler;
- public void run() {
- Looper.prepare();
- mHandler = new Handler() {
- public void handleMessage(Message msg) {
- // 你的方法
- }
- };
- }
- Looper.loop();
- }
首先,一个线程先Looper.prepare(),创建一个Looper,在这个prepare()方法中,回头看一眼基本法里的代码,它会在 return 中new 一个(Looper(true));其实,就是下面的代码:
- private Looper(boolean quitAllowed) {
- mQueue = new MessageQueue(quitAllowed);
- mRun = true;
- mThread = Thread.currentThread(); //绑定当前线程
- }
现在驱动轮有了,履带有了,要让这个流水线动起来,显然,还需要另外一个操作。
没错,这个操作就是例子A中倒二行的Looper.loop()。其源码为:(仅列出你需要理解的代码,其他你不需要关心)
- public static void loop() {
- final Looper me = myLooper();//获取当前线程的Looper
- if (me == null) { //如果没有为当前线程进行Looper.prepare(),跳出异常
- throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
- }
- final MessageQueue queue = me.mQueue; //获得当前Looper me所绑定的MessageQueue
- for (;;) { //无限循环
- Message msg = queue.next(); // 通过MessageQueue的next()方法从队首取一个消息
- if (msg == null) {
- //如果消息队列为空,就退出这个无限循环
- return;
- }
- msg.target.dispatchMessage(msg); //分发消息,msg.target其实就是个handler,你先记着不要管
- msg.recycle(); //通过MessageQueue的recycle()方法回收资源,让"履带"转动取来
- }
- }
上面的loop()中我给出了详细的注解,你稍微花两分钟就能看明白。第8行,从MessageQueue队列中取走第一个消息,然后在第13行,调用msg.target的disspachMessage()方法,分发这个消息。其实msg.target就是个handler,至于为什么,我会在Handler的部分进行讲解,你先这个记着。
Looper部分总结一句话:
在线程的开头,为这个线程准备一个Looper(Looper.prepare()),这个Looper会自动绑定上一个MessageQueue,然后在线程的最后,通过Looper.loop()方法,让这个MessageQueue转动起来,传送这个MessageQueue上的消息对象Message。每次Message被传送到队首,这个Message会被disspatchMessage()方法分发出去,分配到管理它的Handler(流水线工人)那里进行处理。
2.Message
我们在图中做了一个类比,把Message当成了一个包裹,那么它里面到底包裹了啥?我们来看一下它的源码:
- public final class Message implements Parcelable {
- public int what;
- public int arg1;
- public int arg2;
- public Object obj;//以上是一些数据类型,无视
- public Messenger replyTo;
- Bundle data;//一般用于封装数据的包
- Handler target;//注意看这里,是个Handler
- Runnable callback;//注意这个回调
- ......
- }
一个handler通过post方法(我们下面再说,总是就是线程把这个消息Message丢给了Handler)拿到一个Message之后,这个Handler并不是马上处理这个消息,而是先盖上一个章:
- msg.target=this;
有的同学可能会问了,Handler拿到Message为什么不马上处理呢?
原因是:本身Handler并没有提供并发解决机制,但MessageQueue的next()提供了并发解决机制。稍微理解一下这句话,很容易理解的。要知道Handler不只能接收到本线程丢过来的Msg包,还能接到其他线程(一般是子线程)丢过来的包(参考第一幅图),你不搞个基本法,排队来解决,这个程序怕是药丸。
这里还要注意一下那个Runnable callback的回调。现在先别管,总之先记着,我挖的坑我肯定会填的。
Message要注意的只有两种用法,一个是把信息封装,一个是解包提取信息;
- Message msg = Message.obtain();//尽量不要一直new Message(),原因很简单,省内存。
- Bundle b=new Bundle();//信息封包
- b.putInt("Yidong",10086);
- msg.setData(b);
- //msg.sendToTarget();
- myHandler.post(msg);//先丢给流水线工人盖章、入列
- Bundle b=msg.getData();//在handlerMessage()方法中解包提取信息。至于这个方法是啥,马上就要说到了。
- int a=b.getInt("Yidong");//a=10086
一句话总结,Message就是个"包裹",里面装了你需要传递信息,然后被丢来丢去(╯‵□′)╯︵,最后被分配到它的工人那里拆包进行处理。
3.Handler
终于,这篇文章要写完了。QAQ
接下来,我们要说我们的主角了——Handler了。大部分时候,你不需要关心MessageQueue和Looper是怎么工作的,但是Handler是你时时刻刻都必须打招呼的家伙。
首先是Handler究竟是个什么家伙。我把它类比为流水线上"工人" ,它即负责把收到的消息入列,也负责处理队首属于自己的那一份Message。
它的构造函数里没有啥东西,你只需要知道,它会先获取当前线程的Looper并绑定,然后从这个Looper获取到它的MessageQueue。然后,Handler与Looper、MessageQueue的关系就建立起来了。另外,他还创建了一个mCallback。这个待会儿再说。
刚刚我们一直在说msg.target.dispatchMessage()方法(其实也就是msg绑定的handler的disspatchMessage()),那么这个方法到底是个啥东西呢?看源码:
- public void dispatchMessage(Message msg) {
- if (msg.callback != null) {
- handleCallback(msg);
- } else {
- if (mCallback != null) {
- if (mCallback.handleMessage(msg)) {
- return;
- }
- }
- handleMessage(msg);
- }
- }
这一整段的代码就是告诉你:要分发这个代码,先看这个包裹的callback有没有绑定上啥东西(一个Runable);如果有,直接交由这个Runable进行处理,如果没有,查看当前handler的mCallback有没有绑定上啥东西;如果有,交由这个mCallback处理,如果没有,那么就调用当前handler的handleMessage()方法处理。
你可能要问,这个mCallback到底是个啥玩意?其实就是这个玩意:
- public interface Callback {
- public boolean handleMessage(Message msg);
- }
现在要说的是handleMessage()方法,它的源码:
- public void handleMessage(Message msg) {
- //填入你自己的方法
- }
当然了,这个handleMessage()方法就是这个"包裹"Message被丢来丢去后最后要被进行处理的地方(被丢给Runable处理的不算),你当然要重写这个方法,给出你自己的处理方法了。
比如,把我上面写的那个解包提取信息的语句写进去......
一句话总结:
Handler是整个工作流水线的"传递者"和Message"包裹"的"分发者"(比如甩给Runnable)、"处理者",是流水线的"工人们"。
好像,都写完了?
其实并没有,似乎,我们还有个Handler的post()方法没说。这个方法,就是线程把"包裹"丢给Handler,让Handler送其入列的方法。
4.Handler.post()
这个post到底有哪些方法呢?
- public final boolean sendMessage(Message msg);//丢包法1,不吵吵直接丢
- public final boolean sendEmptyMessageDelayed(int what, long delayMillis);//丢包法2,延迟一段时间后丢一个空包,只含一个空的数据what=0,告诉Looper:“嘿哥们你还没空,继续转~”
- public final boolean sendMessageDelayed(Message msg, long delayMillis);//丢包法3,延迟一段时间后丢
- public boolean sendMessageAtTime(Message msg, long uptimeMillis);//丢包法4,在指定的时间丢
丢包法1中其实最后调用了丢包法2,2中调3,3中调4,4中调用了enqueueMessage(queue, msg, uptimeMillis),终于把这个包丢进了流水线"履带"MessageQueue。在enqueueMessage()方法中,会进行msg.target=this的操作,也就是我们刚刚说的"盖章"。
源码:
- public final boolean sendMessage(Message msg){
- return sendMessageDelayed(msg, 0);
- }
- public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
- Message msg = Message.obtain();
- msg.what = what;
- return sendMessageDelayed(msg, delayMillis);
- }
- public final boolean sendMessageDelayed(Message msg, long delayMillis){
- if (delayMillis < 0) {
- delayMillis = 0;
- }
- return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
- }
- public boolean sendMessageAtTime(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);
- }
别急,别忘了,handler其实还有个"分发者"的身份,把信息丢给Runnable处理的方法把?那么是怎么做的呢?其实一个Handler还有这个方法:
- public final boolean post(Runnable r)
- public final boolean postDelayed(Runnable r, long delayMillis)
- public final boolean sendMessage(Message msg)
- public final boolean sendEmptyMessage(int what)
你可能要问,我一个好好的Runnable,怎么到了你Handler就变成一个Message了呢?
其实吧,Hander内部提供了getPostMessage方法把Runnable对象转化为Message:
- private static Message getPostMessage(Runnable r) {
- Message m = Message.obtain();
- m.callback = r;
- return m;
- }
好的,到了这里,我们把这个利用Looper、MessageQueue、Handler进行消息传递的流程总结一下:
一个线程,首先进行Looper.prepare(),就可以创建出一个绑定了MessageQueue"履带"的[唯一]的Looper+MessageQueue"流水线";然后线程可以实例化出几个Handler"工人"。线程有要处理的信息"包裹"Message了,丢给对应的Handler"工人";这个工人判断一下这个到底是个Runnable还是Message,如果是Runnable就包装成一个Message,再"盖章",然后丢向流水线,让它排队;不过不是,"盖完章"不多bb直接甩进流水线。一个Message"包裹"到了流水线的队首,就要被拿出来,根据刚刚盖的章,各找各妈各回各家,该上哪上哪,然后进行msg.target.diapatchMessage()->msg.target.handleMessage()拆包处理。
看完这个总结,再去看我的图,是不是理解了?
恩,其实还有一点:你看我给的图的右边,还有个Thread 2,里面也站了一个Handler"工人",它负责把Thread 2要发给Thread 1的包裹丢进Thread 1的流水线。在编制上,他是Thread 1的"工人"(在Thread 1中实例化)。一般来说,Thread 2其实是 Thread 1的子线程。
为什么说是子线程呢?废话,要是Thread 1 在Thread 2 之前结束了,这名"工人"就被内存杀掉了,包要丢给谁?如果是子线程就放心,要么一起死,要么Thread 2死在 Thread 1之前。