小知识:Handler中post/send

本篇内容很简单,纯属记录方便日后记忆。

Handler消息机制细节就不多说了。我们知道,Looper不停的从消息队列中取出Message,然后分发给对应的Handler去处理。Handler附属于哪个线程取决于Handler构造时对应的 Looper附属的线程,即Handler构造的时候就确定了,它终究要为哪个线程的消息分发后的处理进行服务,也就决定了执行 Handler#dispatchMessage所在的线程。

消息分发

Message和Handler关联的方式很简单,用哪个Handler发送的消息,就用哪个Handler进行任务处理。最终会调用 Handler#dispatchMessage 进行消息处理:

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

我们看到无论如何会有一个 Message 对象分发过来,Message对象可以选择性的携带一些数据。

dispatchMessage 进行分发的时候分了3种情况:
1、如果 msg对象 中有 callback 属性,直接调用 callback#run 方法 「callback是一个实现了Runnable接口的实例」
2、Handler 对象中有 mCallback属性,直接调用 mCallback#handleMessage,如果mCallback#handleMessage返回为true,分发结束;
3、如果mCallback#handleMessage返回false,则继续执行 Handler#handleMessage进行消息分发。

这里说明一下mCallback,不是Runnable类型,而是实现了如下类型「Callback」的实例,区别是有入参和返回值。

public interface Callback {
    boolean handleMessage(@NonNull Message msg);
}
Message发送

针对这种情况,在发送Message的时候演化了很多种形式:【这里简单列几种】
首先定义Handler:

    class MyHandler : Handler {
        constructor() : super()
        constructor(callback: Callback) : super(callback)
        override fun handleMessage(msg: Message) {
            Log.e(MainActivity::class.java.name, "Handler - handleMessage: ${msg.what}")
        }
    }
一、 Handler#postXXX(@NonNull Runnable r)
    private val handler0 = MyHandler()

    handler0.post {  // kotlin : lambda表达式
       Log.e(MainActivity::class.java.name, "Runnable - run")    
    }

最终消息分发回走上边的第一种情况,直接结果:

    MainActivity: Runnable - run
二、 Handler#sendXXX(XXX)
    private val handler1 = MyHandler(Handler.Callback {msg ->
        Log.e(MainActivity::class.java.name, "Callback - handleMessage: ${msg.what}")
        true  //这里
    })

    handler1.sendEmptyMessage(11)

最终消息分发回走上边的第二种情况,直接结果:

    MainActivity: Callback - handleMessage: 11
    private val handler2 = MyHandler(Handler.Callback {msg ->
        Log.e(MainActivity::class.java.name, "Callback - handleMessage: ${msg.what}")
        false  //这里
    })

    handler2.sendEmptyMessage(11)

最终消息分发回走上边的第三种情况,直接结果:

    MainActivity: Callback - handleMessage: 11
    MainActivity: Handler - handleMessage: 11

总结:总体来说 post 的参数是Runnable,send的参数有一部分是 Message。不论哪种情况都会最终构建一个Message对象,然后发送到对应线程的消息队列中。

还记得 Activity#runOnUiThread 方法的实现,也是使用了post的方法:

    public final void runOnUiThread(Runnable action) {
        if (Thread.currentThread() != mUiThread) {
            mHandler.post(action);
        } else {
            action.run();
        }
    }
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容