android: Handler 源码浅析 [Handler,Looper,Message,MessageQueue]

本文围绕Android中重要且常用的对象展开,介绍了其处理异步回调的用途及相关系统实现。给出使用示例,阐述了Handler、Looper、Message、MessageQueue的关联及创建过程,分析了调用流程,并解答了主线程创建Handler无需调用特定方法的问题。

android中,Handler是非常重要且常用的对象。往往用来处理异步回调。很多系统实现都使用到了Handler。比如AsyncTask,IntentService,HandlerThread 等。

先给出一个简单是使用示例:

// Handler 使用示例 ### 
// MyActivity.java
    private Handler mainHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
//            super.handleMessage(msg);
            Log.d(TAG, "handlerMessage==" + msg.what);
        }

        @Override
        public void dispatchMessage(Message msg) {
            super.dispatchMessage(msg);

            Log.d(TAG, "dispatchMessage==" + msg.what);
            Log.d(TAG, "dispatchMessage==handler ### " + msg.getTarget());
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_self);

        findViewById(R.id.button_click)
                .setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Log.v(TAG, "click this button...");
                        Message obtain = Message.obtain();
                        obtain.obj = new Date();
                        obtain.what = 12;
                        mainHandler.sendMessage(obtain);
                    }
                });
    }

(一般是在子线程中处理完成耗时操作之后,)将结果发送到主线程,此时往往会调用Handler#sendMessage(msg);方法。


说到Handler,往往跟 LooperMessage 一起来说,因为他们确实是密不可分的。

在使用Handler的使用
首先,通过Handler的构造方法创建Handler对象,并获取当前线程的Looper对象,以及Looper中的MessageQueue对象。

// Handler 的无参构造,实际上调用的是该构造方法
    public Handler(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;
    }

这里将Handler与Looper 对象关联了。mLooper = Looper.myLooper(); 很简单,就是这样一句代码就完成了。

根据 android: Looper 源码浅析 [Handler,Looper,Message,MessageQueue] 这里的分析可知:

// Looper.java
    public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }

是通过ThreadLocal#get()去获取的。
通过以上分析可知。创建Handler的时候,同时获取到了对应的Looper对象。

这里也可以看出ThreadLocal的威力。不需要你去专门指定key,只要是在当前线程,那么get()到的,就是之前你ThreadLocal#set()进去的对象。

设置进去,是在Looper#prepare()的使用。

handler.sendMessage()Handler内部,真正调用的是Handler#enqueueMessage()方法。

    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;  // --> 绑定 message 与 handler  ###
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

该方法很重要,将MessageHandler对象关联起来了。

对于Handler,只要关注其构造方法,以及两个重要的方法sendMessage(),dispatchMessage()即可。

【粗粒度】整体看一下调用流程。首先,通过调用Handler#sendMessage()发送对应的Message对象;然后Looper.loop()方法中会拿到这个Message对象,并调用msg.target.dispatchMessage()方法,让Handler#dispacthMessage(msg)被调用。这样就可以通过重写Handler#dispatchMessage(msg)或者Handler#handlerMessage(msg)方法来拿到之前通过Handler#sendMessage(msg)发出的Message对象了。

  • 问题1:为什么在主线程创建的 Handler不需要调用Looper.prepare()以及Looper.loop()方法?
    答案很明确,系统已经帮忙创建了。(在ActivityThread里面。)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值