欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android异步消息处理机制之Handler

程序员文章站 2022-07-14 14:34:22
...

在Android中异步消息处理机制有Handler以及AsyncTask两种方式,而AsyncTask也是Handler的封装,今天就学习一下Handler机制。

与Handler消息机制相关的类主要有以下四个:

  • Handler
  • Message
  • MessageQueue
  • Looper

Handler主要用于发送消息,以及处理消息。发送消息的方法主要是post和send两种。

post方法有:

    public final boolean post(Runnable r)
    {
       return  sendMessageDelayed(getPostMessage(r), 0);
    }
    
    public final boolean postAtTime(Runnable r, long uptimeMillis)
    {
        return sendMessageAtTime(getPostMessage(r), uptimeMillis);
    }
    
     public final boolean postAtTime(Runnable r, Object token, long uptimeMillis)
    {
        return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
    }
    
    public final boolean postDelayed(Runnable r, long delayMillis)
    {
        return sendMessageDelayed(getPostMessage(r), delayMillis);
    }
    
     public final boolean postDelayed(Runnable r, Object token, long delayMillis)
    {
        return sendMessageDelayed(getPostMessage(r, token), delayMillis);
    }
    
     public final boolean postAtFrontOfQueue(Runnable r)
    {
        return sendMessageAtFrontOfQueue(getPostMessage(r));
    }

通过代码可以看出来post方法最终还是调用的send方法,将消息发送到Handler所在的线程中;

send方法有:

    public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 0);
    }
    
     public final boolean sendEmptyMessage(int what)
    {
        return sendEmptyMessageDelayed(what, 0);
    }
    
    public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
        Message msg = Message.obtain();
        msg.what = what;
        return sendMessageAtTime(msg, uptimeMillis);
    }
    
    public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
        Message msg = Message.obtain();
        msg.what = what;
        return sendMessageDelayed(msg, delayMillis);
    }
    
    public final boolean sendMessageAtFrontOfQueue(Message msg) {
        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, 0);
    }
    
   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);
    }
    
    public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }

通过翻看源码,我们可以知道除了sendMessageAtFrontOfQueue方法外,其它的send方法最终调用的都是sendMessageAtTime方法,只是封装过程中的参数做了调整。

处理消息

Handler处理消息一般是在创建Handler对象时,重写它的handlerMessage()方法,在该方法中进行处理。

 Handler handler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                //处理消息
            }
 };

Message是消息体,它主要在线程之间传递消息,可以携带少量的信息。一般推荐使用Message的obtain方法,来进行创建Message对象,避免在许多情况下重新分配新对象,当然你也可以通过new Message的方式创建Message对象;对于Message的几个参数,我们需要了解一下:

   /**
     * 用来标识不同的消息
     */
    public int what;

    /**
     * 用来存储整型数据的参数1
     */
    public int arg1;

    /**
      * 用来存储整型数据的参数2
     */
    public int arg2;

    /**
     * 用来存储任意类的对象,在handlerMessage()方法中,可进行强制转换,拿到传递的对象。
     */
    public Object obj;

MessageQueue是消息队列,它主要用于存放Handler发送过来的消息,这些消息将一直存在MessageQueue中,等待被处理,每个线程只有一个MessageQueue对象。MessageQueue对象是在Looper中创建的。

Looper是MessageQueue的管理对象,调用了Looper.loop()方法,就会进入到无线循环状态,当发现MessageQueue中有消息,就将它取出,并传递到handlerMessage()方法中进行处理。每个线程中只会有一个Looper对象。

runOnUiThread()方法是对Handler的封装:

    public final void runOnUiThread(Runnable action) {
        if (Thread.currentThread() != mUiThread) {
            mHandler.post(action);
        } else {
            action.run();
        }
    }

可以看到当前线程不是UI线程时,会将该Runnable对象通过mHandler.post方法发送到线程中,因为runOnUiThread方法是Activity的方法,而mHandler是在Activity中创建,Activity又是运行在主线中,所以mHandler是主线程Handler;如果当前线程是UI线程,则直接运行run方法。