美文网首页
Android中 Handler Message Message

Android中 Handler Message Message

作者: 遇见的延长线 | 来源:发表于2021-05-29 00:55 被阅读0次

Message是具体的消息携带者
MessageQueue用来存储Message
Looper开启一个循环从MessageQueue中获取数据并将数据分发给当前线程进行处理
Handler主要用来向MessageQueue中添加数据,同时也处理Looper分发过来的数据

Android中的消息机制,我们主要用来处理子线程和主线程之间的通信,但不是只能处理子线程跟主线程的通信,它也可以处理两个子线程之间的通信。取决于Handler创建时传入的Looper,Handler无参的构造函数是直接获取当前线程的Looper源码如下:

 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;
    }

 /**
     * Return the Looper object associated with the current thread.  Returns
     * null if the calling thread is not associated with a Looper.
     */
    public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }

Looper与当前线程的关系是一个线程只能有一个Looper存在,Looper与MessageQueue的关系是一个Looper只能有一个MessageQueue存在。
Android 中Looper是不能直接通过new来直接创建的,需要调用Looper.prepare()来实现Looper的创建,而在Looper中有个静态变量sThreadLocal用来存储当前线程的具体实例来达到一个线程只有一个Looper的目的,具体源码如下:

 /** Initialize the current thread as a looper.
      * This gives you a chance to create handlers that then reference
      * this looper, before actually starting the loop. Be sure to call
      * {@link #loop()} after calling this method, and end it by calling
      * {@link #quit()}.
      */
    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));
    }

MessageQueue只有一个是因为在Looper中定义了final类型的MessageQueue变量,在Looper初始化的时候调用了MessageQueue的赋值。

@UnsupportedAppUsage
final MessageQueue mQueue;

private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

我们主要来说一下Handler,如下是Android官方对Handler的解释

A Handler allows you to send and process {@link Message} and Runnable
objects associated with a thread's {@link MessageQueue}. Each Handler
instance is associated with a single thread and that thread's message
queue. When you create a new Handler, it is bound to the thread /
message queue of the thread that is creating it -- from that point on,
it will deliver messages and runnables to that message queue and execute
them as they come out of the message queue.
<p>There are two main uses for a Handler: (1) to schedule messages and
runnables to be executed at some point in the future; and (2) to enqueue
an action to be performed on a different thread than your own.

就是说它有两个作用

  • 调度Message和Runnable在未来某一时刻执行
  • 将不同线程上执行的操作添加到队列里

Handler send系列的发送Message的方法如下:

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

我们发现前几个方法最后都是调用的sendMessageAtTime(@NonNull Message msg, long uptimeMillis)这个方法。

post系列的方法如下:

 public final boolean post(@NonNull Runnable r) {
       return  sendMessageDelayed(getPostMessage(r), 0);
    }
 private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }
......

我们发现post系列的方法与send系列不同的是 post为Message添加了Runnable,那么这个Runnable是做什么用的呢?

我们通过查阅源码发现handler在处理消息的分发的时候有对msg.callback的判读,一起看一下源码:

public void dispatchMessage(@NonNull Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

也就是说post系列方法直接设置了回调,我们可以直接在Runnable中进行自己的处理,而send系列的方法只能在handler的callback或者 重写的handlerMessage方法中处理自己的操作。

相关文章

网友评论

      本文标题:Android中 Handler Message Message

      本文链接:https://www.haomeiwen.com/subject/ikossltx.html