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

Android通信机制--Handler

程序员文章站 2022-07-14 21:58:17
...

Android通信机制–Handler

Handler机制大概是android开发过程中最常遇到的通信机制,简单说就是Looper从消息队列中不断去除消息进行处理。Handler通信中最核心的组件应该就是Handler,Looper,MessageQueue,Message了,这几个组件是如何构成消息的循环呢,我们先自己写个demo看看。

private Handler mHandler;
private void handlerDemo() {
    new Thread(new Runnable() {
        @Override
        public void run() {
            Looper.prepare();
            mHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    if (msg.what == 100) {
                        Log.d(TAG, "handler self");
                    }     
                }
            };
            Looper.loop();
        }
    }).start();
}  

发送消息的代码如下:

mHandler.sendEmptyMessage(100);  

这就是Handler的基本用法,接下来我们分析下这其中的原理。通过代码可以知道,最重要的应该是Looper.prepare()Looper.loop()这两个函数了。这两个函数内部是如何实现的呢?看下Looper.prepare():

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

可以发现最终调用到了prepare(boolean quitAllowed)中,继续发现新建了一个Looper并赋值给了一个ThreadLocal类型的变量sThreadLocal,看到这里可以发现,调用Looper.prepare()函数其实就是给当前的Thread设置了一个Looper类型的变量,而且每个线程只能设置一次。
接下来看下new Looper(quitAllowed)内部实现了什么逻辑。

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

终于看到MessageQueue了,这个quitAllowed表示消息队列是否可以退出。可以发现Looper的构造函数新建了一个消息队列MessageQueue以及记录了当前的线程。
接下来就是消息循环了,消息循环从Looper.loop函数开始。

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

       ......
        try {
            msg.target.dispatchMessage(msg);
        } finally {
            if (traceTag != 0) {
                Trace.traceEnd(traceTag);
            }
        }

        ......

        msg.recycleUnchecked();
    }
}  

代码已经非常清晰了,调用loop()函数后,首先判断当前是否已经调用prepare()函数,如果已经调用,则进入for循环,不断去除消息队列中的消息。如果消息不为空,则调用msg.target.dispatchMessage(msg)函数进行处理,msg.target其实就是发送这个消息的handler,调用dispatchMessage函数对消息进行处理。

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

以上就是handler, Looper, Message三个组件是如何实现消息处理的。可能会有疑问,在这个位置使用Handler机制时调用了Looper.prepare和Looper.loop函数,但是为什么我们自己在Activity中可以直接新建Handler并进行消息处理呢。想想感觉应该在哪个位置调用这两个函数。
扒扒ActivityThread的源码,你就会恍然大悟:

public static void main(String[] args) {
    ......

    Looper.prepareMainLooper();

    ......
    Looper.loop();

    throw new RuntimeException("Main thread loop unexpectedly exited");
}  

终于发现了,是不是很明了。