Android源码系列(11) -- HandlerThread

June 13, 2018

一、类签名

HandlerThread是Android提供的封装类,父类是Thread。HandlerThread实例包含一个Looper并用于构建Handler。由于这是一个线程类,所以必须通过Thread.start()启动线程。

1
public class HandlerThread extends Thread

二、数据成员

线程优先级

1
int mPriority;

线程id

1
int mTid = -1;

线程Looper

1
Looper mLooper;

通过上述Looper构建的Handler

1
private @Nullable Handler mHandler;

三、构造方法

构造方法,默认线程优先级

1
2
3
4
public HandlerThread(String name) {
    super(name);
    mPriority = Process.THREAD_PRIORITY_DEFAULT;
}

构造方法,自定义线程优先级

1
2
3
4
public HandlerThread(String name, int priority) {
    super(name);
    mPriority = priority;
}

四、成员方法

此类本质是线程,必须使用Thread.start()启动。

当线程的Looper通过loop()方法启动后,就会在该方法内轮询获取消息。只有在Looper退出后,下一行 mTid = -1; 才会执行,重置线程id后结束run()的运行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Override
public void run() {
    // 获取线程Tid
    mTid = Process.myTid();
    
    // 初始化Looper
    Looper.prepare();
    
    // 获取Looper
    synchronized (this) {
        mLooper = Looper.myLooper();
        notifyAll();
    }
    
    // 设置线程优先级
    Process.setThreadPriority(mPriority);
    onLooperPrepared();

    // 启动Looper
    Looper.loop();
    mTid = -1;
}

重写此方法以便在Looper开始loop前执行自定义操作

1
2
protected void onLooperPrepared() {
}

获取线程中的Looper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public Looper getLooper() {
    // 线程不是存活状态则返回null
    if (!isAlive()) {
        return null;
    }

    // 即使thread已经启动,Looper实例也只在其创建完成后才能返回
    synchronized (this) {
        while (isAlive() && mLooper == null) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
    }
    return mLooper;
}

从HandlerThread里面获取共享的Handler实例

1
2
3
4
5
6
7
@NonNull
public Handler getThreadHandler() {
    if (mHandler == null) {
        mHandler = new Handler(getLooper());
    }
    return mHandler;
}

调用Looper的退出方法quit()

1
2
3
4
5
6
7
8
public boolean quit() {
    Looper looper = getLooper();
    if (looper != null) {
        looper.quit();
        return true;
    }
    return false;
}

调用Looper的安全退出方法quitSafely()

1
2
3
4
5
6
7
8
public boolean quitSafely() {
    Looper looper = getLooper();
    if (looper != null) {
        looper.quitSafely();
        return true;
    }
    return false;
}

获取线程id,即Process.myTid()

1
2
3
public int getThreadId() {
    return mTid;
}