Handler机制源码探索(一):UI线程中Handler的初始化流程

最近用到Handler,感觉很神奇,不过一直仅仅只停留在会使用的地步,这段时间抽出一点时间来看看源码。

我们都知道,Handler的使用无法离开几个类,Looper、Message以及MessageQueue。

其中Message类不用多说,是用来传递各类参数或消息所用的类,当handler.sendMessage() 或者 msg.sendToTarget() 时,被发送的Message对象则会进入到MessageQueue中。Looper则作为MessageQueue的管理类,不断的从MessageQueue中取出Message,并让对应的handler去处理调用handleMessage(Message msg)。让我们来看一下源码在这里是怎么实现的。

我们就以Handler在Activity中的初始化的开始吧。

package com.example.devin.test;

import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    private TextView mTextView = null;
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            mTextView.setText(msg.obj.toString());
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTextView = (TextView) findViewById(R.id.hello);
        new Thread() {
            @Override
            public void run() {
                Message msg = mHandler.obtainMessage();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                msg.obj = "Hi I'm from thread.";
                mHandler.sendMessage(msg);
            }
        }.start();
    }
}


我们先来看下Handler的构造方法。在上面的代码中,我们初始化Handler时,使用的是无参的构造方法。

    public Handler() {
        this(null, false);
    }
最终调用构造器为:
    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 that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }
我们可以看到,当实例化Handler时,会调用
       mLooper = Looper.myLooper();

我们再来看下myLooper()方法:

    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>   /*...Others...*/
    //sThreadLocal声明及初始化 
    public static @Nullable Looper myLooper() { return sThreadLocal.get(); }
我们知道ThreadLocal可以用来在线程数据内共享某些数据。当无法取到时,则会返回null。但是如果myLooper()方法返回null,按理来说我们的demo也应该抛出异常“Can't create handler inside thread that has not called Looper.prepare()”,可是为啥没报错呢?

原来是这样,在Activity初始化时,会在ActivityThread中的main方法中,调用Looper.prepareMainLooper(),会为UI线程创建一个Looper并保存到sThreadLocal属性中,自然不会出现此问题。所以说,在UI线程中,会自动创建一个Looper,就是在这个时候创建的。在Demo中当new Handler时,与Handler相关联的即是通过Looper.prepareMainLooper()返回回来的Looper。

    public static void prepareMainLooper() {
        prepare(false);//在此处调用prepare方法,创建Looper。
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }
    /*.....Others......*/
    //prepare方法
    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));//实例化Looper并set至sThreadLocal中。
    }

我们再来看下Looper的构造器:

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

我们可以发现,Looper初始化的时候,初始化了MessageQueue,同时也与当前的线程进行关联。

而当初始化Handler时,也就是将Looper与Handler进行关联,也同时将Looper中的MessageQueue进行关联。

以上,就是Handler在UI线程中的初始化流程。

如有任何错漏,欢迎各位大神指教,小生在此谢过!~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值