Android HandlerThread源码分析

来源:互联网 发布:新疆网络推广 编辑:程序博客网 时间:2024/06/15 00:28

HandlerThread继承自Thread,该类实现了一个带有Looper的线程,ThreadHandler中的Looper可以被用于创建一个Handler,这样可以通过在线程中处理handler中的消息队列;
当然,HandlerThread的实例必须调用start()方法才可以让处理Handler发送的消息,也就是说HandlerThread必须是运行状态的。

源码分析

在HandlerThread类中,核心代码就是在run()方法中创建一个Looper对象。这样就可以通过handler在子线程中处理消息。

public class HandlerThread extends Thread {    int mPriority;    int mTid = -1;    Looper mLooper;    private @Nullable Handler mHandler;    public HandlerThread(String name) {        super(name);        mPriority = Process.THREAD_PRIORITY_DEFAULT;    }    public HandlerThread(String name, int priority) {        super(name);        mPriority = priority;    }    /**     * 在looper启动之前,可用于初始化一些设置     */    protected void onLooperPrepared() {    }    /**     * 在线程中创建Looper     */    @Override    public void run() {        mTid = Process.myTid();        // 1、创建Looper,该looper对象实际被存储在ThreadLocal对象中        Looper.prepare();        synchronized (this) {            // 2、获取Looper对象,通过ThreadLocal.get()获取Looper对象            mLooper = Looper.myLooper();            notifyAll();        }        Process.setThreadPriority(mPriority);        onLooperPrepared();        // 3、启动looper消息循环,在消息队列中获取消息,该方法是一个阻塞的方法        Looper.loop();        mTid = -1;    }    /**     * 获取该线程中的Looper对象     */    public Looper getLooper() {        if (!isAlive()) {            return null;        }        // 当looper被创建后该方法才返回looper对象        synchronized (this) {            while (isAlive() && mLooper == null) {                try {                    wait();                } catch (InterruptedException e) {                }            }        }        return mLooper;    }    /**     * 该方法可以返回一个带有该Looper的Handler的对象,但是该方法被隐藏     */    @NonNull    public Handler getThreadHandler() {        if (mHandler == null) {            mHandler = new Handler(getLooper());        }        return mHandler;    }    /**     * 退出handlerThread的looper循环     *     * 通过该方法退出looper循环,将会移除消息队列中的所有未处理消息     */    public boolean quit() {        Looper looper = getLooper();        if (looper != null) {            looper.quit();            return true;        }        return false;    }    /**     * 退出handlerThread的looper循环     *     * 通过该方法退出looper循环,将会清楚所有pending的消息,但是对于已经存在于消息队列中的消息,handler将会继续处理完成后才会退出循环。     */    public boolean quitSafely() {        Looper looper = getLooper();        if (looper != null) {            looper.quitSafely();            return true;        }        return false;    }    /**     * 返回线程id     */    public int getThreadId() {        return mTid;    }}

通过上面的代码我们可以知道,一旦HandlerThread调用start()方法启动后,Looper对象会一直阻塞等待处理消息队列中的消息,直到你线程调用quit()或quitSafely()方法,looper循环器才会停止运行,整个线程才会停止。

HandlerThread使用场景

通常情况下,都是通过HandlerThread在子线程中执行耗时的操作。同时,因为在HandlerThread中是通过Looper维护的消息队列,所以线程在处理任务时时同步的,所以就不需要考虑并发的问题。

代码示例:

HandlerThread handlerThread = new HandlerThread("WorkThread");handlerThread.start();Handler handler = new Handler(handlerThread.getLooper()) {    @Override    public void handleMessage(Message msg) {        super.handleMessage(msg);        // 这里可以执行耗时操作,因为在子线程中    }};

IntentService

在android源码中,有一个IntentService的服务类,该类继承自Service,主要功能就是让Service在子线程中处理任务,在该类中就是通过HandlerThread实现的。

关于IntentService的介绍,请看 Android IntentService源码分析

Handler、Thread和HandlerTrhead的关系

一句简单的话总结这三者的关系就是:
HandlerThread就是一个在Thread中实现handler的机制的一个具体实现。

在这里明确一个概念,如果想在子线程中创建Handler,那么必须在handler初始化前为该线程创建一个Looper对象,否则会抛出一个运行时异常:

java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()                                                       at android.os.Handler.<init>(Handler.java:200)                                                       at android.os.Handler.<init>(Handler.java:114)                                                       at com.zhangke.componentdemo.MainActivity$1.run(MainActivity.java:30)

通常情况下,我们通过下面的代码为线程创建Looper:

  class LooperThread extends Thread {      public Handler mHandler;      public void run() {          Looper.prepare();          mHandler = new Handler() {              public void handleMessage(Message msg) {                  // process incoming messages here              }          };          Looper.loop();      }  }

关于HandlerThread的介绍就到这里了。