美文网首页
Android之HandlerThread的探索

Android之HandlerThread的探索

作者: 放码过来吧 | 来源:发表于2018-03-20 18:25 被阅读104次

之前分析了IntentHandler的内部实现原理,里面用的就是HandlerThread来进行异步处理事件(想看可以点击intentHandler),然而当时并没有解释HandlerThread跟普通的Thread的区别,现在来分析下它的内部实现相关。

问题提出
1、HandlerThread是什么?
2、HandlerThread跟普通的Thread有何区别?
3、HandlerThread内部实现分析。
4、HandlerThread使用场景。


1.jpg

分析与解决问题
我们先看看源码里面对HandlerThread的解释:

/**
 * Handy class for starting a new thread that has a looper. The looper can then be 
 * used to create handler classes. Note that start() must still be called.
 */

大概讲的意思就是:HandlerThread是一个拥有looper的子线程,这个looper可以用来创建handler类。注意,创建的HandlerThread对象的start()方法一定要执行。
很好,现在我们知道了,HandlerThread是一个继承与Thread的子线程,区别就在于,HandlerThread提供了创建handler对象的looper。
接下来,看看它的内部实现:

    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }

    /**
     * Constructs a HandlerThread.
     * @param name
     * @param priority The priority to run the thread at. The value supplied must be from 
     * {@link android.os.Process} and not from java.lang.Thread.
     */
    public HandlerThread(String name, int priority) {
        super(name);
        mPriority = priority;
    }

构造函数里面的mPriority,优先级相关的,可以根据自己的需求去设置。

    @Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }

在Looper.prepare()里面,其实就是创建looper对象,并赋值给mLooper.onLooperPrepared()里面是空方法,我们可以重写,做一些初始化的操作,然后调用Looper.loop()方法启动了了loop。在这里,我们有一些疑惑,synchronized?notifyAll()?稍后我们在来分析,我们先看看prepare()内部实现:

 public static void prepare() {
        prepare(true);
    }

    /**
     * sThreadLocal.get() will return null unless you've called prepare().
     */
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    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对象放到的sThreadLocal。放进去总要取出来吧,我们来看看Looper.myLooper()内部的实现:


    /**
     * 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创建了,总要用上吧,这个时候就应该想到handler了,我们来看看提供的获取handler的方法getThreadHandler():

    /**
     * @return a shared {@link Handler} associated with this thread
     * @hide
     */
    @NonNull
    public Handler getThreadHandler() {
        if (mHandler == null) {
            mHandler = new Handler(getLooper());
        }
        return mHandler;
    }

这个方法可以获取一个有当前子线程looper的handler对象,我们来看看getLooper(),可以看出是获取looper对象的方法:

   /**
     * This method returns the Looper associated with this thread. If this thread not been started
     * or for any reason isAlive() returns false, this method will return null. If this thread
     * has been started, this method will block until the looper has been initialized.  
     * @return The looper.
     */
    public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }
        
        // If the thread has been started, wait until the looper has been created.
        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }

这里面,isAlive()方法的意思是线程不正常运行就返回null,接着,如果looper还没创建好就wait()等待,创建后notifyAll。在这里,我们来分析下为什么会用到wait,notifyAll等相关:handler对象的创建方法(getThreadHandler())调用是在UI线程里面,but,Looper在一个线程中执行创建的,为了确保looper创建完成之后在创建handler对象,所以需要wait(),notify()来处理线程同步问题。

总结:HandlerThread其实就是一个封装了handler的Thread的子类,做好前奏工作后,让我们在线程中直接使用handler来处理一个或者多个异步操作。使用场景,就是适合那些多个并按顺序执行的耗时任务的相关需求,可以跟intentService配合使用。(intentService内部异步处理用的就是HandlerThread)

相关文章

网友评论

      本文标题:Android之HandlerThread的探索

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