Android中的Handler, Looper, MessageQueue

      Handler 和 Looper 是android 系统线程间协作的基础。

      一个应用在主线程都有一个MainHandler 和 MainLooper,是由android 环境为其创建的,用户不必单独处理,直接拿过来用就可以。

     在讲Handler Looper MessageQueue之前先说说handler和looper之间的联系和区别。

区别:

      两者都和MessageQueue打交道,但Handler是向MessageQueue发送消息,这个发送是由Message来完成的,通过Message的sendToTarget()把消息发出去,然后调用handler的sendMessage(queue.enqueueMessage)。

            Message msg = handler.obtainMessage();

            msg.what = ... //  注意:msg.target 其实就是你传进来的handler实例

            ......

            msg.sendToTarget();

      在Message的sendToTarget()方法里,调用了Handler的sendMessage()方法,如下:

           target.sendMessage(msg)

     而Looper是从MessageQueue中取出消息(queue.next()).

联系:

    1.Handler 依赖 Looper,每一个Handler必然有一个mLooper的成员变量。 Handler 的MessageQueue就是获取Looper的MessageQueue, 即Handler和Looper共享一个MessageQueue。在Handler的构造方法中有如下定义:

              mLooper = Looper.myLooper();

              mQueue = mLooper.mQueue;

       由此可以看出,Handler对应两个实例,一个是Looper,一个是MessageQueue,但是MessageQueue其实就是Looper里的MessageQueue。

    2.Looper取出MessageQueue在执行的时候(Looper.loop()方法,其实就是一个无限循环,死循环),实际上运行的是Handler的方法msg.target.dispatchMessage(msg)。

      在loop()方法里,Looper取得mLooper实例,并获得MessageQueue,对MessageQueue做出队调用,如下:

               final Looper me = myLooper();

               final MessageQueue queue = me.mQueue;

               for (;;) {

    Message msg = queue.next();

                    msg.target.dispatchMessage(msg);

                    msg.recycle();

               }

      在继续下面的讲解之前在说说Looper和Thread之间的关系.

      Looper依赖于Thread, Looper是一个消息循环体,在Thread中运行,从MessageQueue中取出下一条Message,分发到该消息的target, 即Handler。

     Android系统启动一个Application的时候,会创建Main线程,也就是通常所说的UI线程,还有Looper,Handler,MessageQueue。即系统为用户创建UI线程的Looper和Handler还有MessageQueue。

     但是如果当用户自己创建了一个Thread,就要自己去为该线程创建Looper,MessageQueue和Handler。

               class LooperThread extends Thread {

                     public Handler mHandler;

        @Override

                     public void run() {

                           Looper.prepare();// 这是为该线程创建Looper对象

                           mHandler = new Handler() {

                                public void handleMessage(Message msg) {

                                     // process incoming messages here

                                }

                           };

                         Looper.loop();

                     }

                }

     注意: 1. new Handler(), 这个Handler是当前线程的Handler。

               2.Looper.myLooper() 获得的是当前线程的Looper.

总结一下:消息处理机制主要是为异步刷新UI来设计的,当然异步刷新有如下几种方式:

        1. Activity.runOnUiThread(Runnable)

        2. View.post(Runnable)

        3. View.postDelayed(Runnable, long)

        4. Handler机制

      这里主要是因为对UI的操作要求是Thread-safe, 非UI线程来完成View的刷新会出现各种问题。什么问题呢,仔细想想就知道了。

    总结一:Message Looper Handler 实现

         1. 初始化Handler实例, 设置 mLooper, mQueue。

                  Handler handler = new Handler();

         2. 获取Message实例。

                  (1) Message msg = handler.obtainMessage(); // recommend

                  (2) Message msg = new Message();// 可以这样做,至于为什么可以,自己去想吧

         3. 发送Message, 消息入队enqueue(msg)

                  msg.target = handler;

                  msg.sendToTarget();//其实调用的是target.sendMessage(msg), target = msg.target

                  target.mQueue.enqueue(msg);

          4. Looper从MessageQueue取出下一个Message,去分发这个消息。

                  final Looper me = myLooper();

                  final MessageQueue queue = me.mQueue;

                  while(true) {

                        Message msg = queue.next();

                        msg.target.dispatchMessage(msg);

                        msg.recycle();

                  }

           5. Handler去处理这个消息。

                  public void dispatchMessage(Message msg) {

                        if (msg.callback != null) {

                               handleCallback(msg);

                        } else {

                               if (mCallback != null) {

                                    if (mCallback.handleMessage(msg)) {

                                          return;

                                    }

                               }

                               handleMessage(msg);

                         }

                  }

      这里会有一些不同,你一定很奇怪msg.callback是什么东西,不要紧,下面马上就要讲了,这里由于我们没有设置callback,所以必然为空,即msg.callback == null,  同样mCallback == null, 直接调用我们自己实现的handleMessage(msg)方法。

 总结二:Message Looper Handler, Runnable 实现

             1. 初始化Handler实例, 设置 mLooper, mQueue。

                  Handler handler = new Handler();

             2. 生成Runnable接口,实现run()方法。

                   Runnable runnable = new Runnable() {

                          @Override

                          public void run() {

                                  // process your job

                          }

                   }

                   handler.post(runnable);

                   这里要解释一下,Message对象的几个成员变量:

                           msg.what      // message code to its handler 

                           msg.target    // handler

                           msg.data      // similar to bundle (如果你不知道Bundle,请参考developer.android.com)

                           msg.callback // Runnable

                   好了,具体的请参看Message.java,  说道这里,应该很清楚了,虽然我们post出去一个Runnable,但是           Handler在后台为我们生成了一个Message对象,并且设置了callback,如下:

                          Message msg = handler.obtainMessage();

                          msg.callback = runnable;

         3. 发送Message, 消息入队enqueue(msg)

                  msg.target = handler;

                  msg.sendToTarget();//其实调用的是target.sendMessage(msg), target = msg.target

                  target.mQueue.enqueue(msg);

          4. Looper从MessageQueue取出下一个Message,去分发这个消息。

                  final Looper me = myLooper();

                  final MessageQueue queue = me.mQueue;

                  while(true) {

                        Message msg = queue.next();

                        msg.target.dispatchMessage(msg);

                        msg.recycle();

                  }

           5. Handler去处理这个消息。

                  public void dispatchMessage(Message msg) {

                        if (msg.callback != null) {

                               handleCallback(msg);

                        } else {

                               if (mCallback != null) {

                                    if (mCallback.handleMessage(msg)) {

                                          return;

                                    }

                               }

                               handleMessage(msg);

                         }

                  }

                这里由于msg.callback != null, 所以直接去调用handleCallback(msg), 如下:

                    private static void handleCallback(Message message) {

                             message.callback.run();

                    }

继续写下去:

        Looper用于在android线程中进行消息处理,默认情况下, 一个线程并不和任何Looper绑定, 当我们调用Looper.prepare()时, 如果当前线程还没有和任何Looper绑定, 那么将创建一个Looper让他和当前线程绑定,当我们调用Looper.loop()时, 它将对当前线程所对应的Looper的Message进行处理,从MessageQueue中取出消息, 处理消息,一直循环,直到对该Looper调用quit()方法。

     对于handler,其实只是把Message发送到对应的Looper的MessageQueue中,最后处理还是在Looper.loop()的死循环里。

     一个Looper可以用于构造多个Handler, 因为Looper.loop()方法是个死循环,会让当前线程一直在那里处理消息,除非对该线程调用quit()方法。 所以,如果想对该Handler发送消息或者添加Runnable进行事务处理,要么在别的线程中进行,要么在该Handler的handleMessage()方法或者Runnable的run()方法中操作。

     注意:

         Handler的构造函数Handler() 和 Handler(Handler.Callback callback) 虽然没有looper参数,但是它实际上市通过Looper.mylooper()来获取当前线程的Looper的。

       

猜你喜欢

转载自hardworking.iteye.com/blog/1744209