Android HandlerThread

01.HandlerThread介绍

1.1 HandlerThread定义

  • HandlerThread是个什么东西,是一个hanlder还是thread,还是别猜了,直接看一下类的定义吧,英文看不懂,可以找翻译?

    • 这个类的作用是创建一个包含looper的线程。
    • 那么在什么时候需要用到它呢?加入在应用程序当中为了实现同时完成多个任务,所以会在应用程序当中创建多个线程。为了让多个线程之间能够方便的通信,会使用Handler实现线程间的通信。这个时候我们手动实现的多线程+Handler的简化版就是我们HandlerThrea所要做的事了。
    1
    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.

1.2 HandlerThread简单使用

  • 看一下HandlerThread的基本用法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    HandlerThread mHandlerThread = new HandlerThread("myHandlerThreand");
    mHandlerThread.start();

    // 创建的Handler将会在mHandlerThread线程中执行
    final Handler mHandler = new Handler(mHandlerThread.getLooper()) {
    @Override
    public void handleMessage(Message msg) {
    Log.i("tag", "接收到消息:" + msg.obj.toString());
    }
    };

    title = (TextView) findViewById(R.id.title);
    title.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {

    Message msg = new Message();
    msg.obj = "11111";
    mHandler.sendMessage(msg);

    msg = new Message();
    msg.obj = "2222";
    mHandler.sendMessage(msg);
    }
    });

1.3 HandlerThread几个特性

  • HandlerThread 继承于 Thread,本身就是一个线程类
  • HandlerThread 在内部维护了自己的 Looper 对象,所以可以进行 looper 循环
  • 创建 HandlerThread 后需要先调用 HandlerThread.start() 方法再向其下发任务,通过 run() 方法来创建 Looper 对象
  • 通过传递 HandlerThread 的 Looper 对象给 Handler 对象,从而可以通过 Handler 来向 HandlerThread 下发耗时任务。

02.HandlerThread源码分析

2.1 HandlerThread构造方法

  • 首先定义了一个HandlerThread对象,是直接通过new的方式产生的,查看其构造方法:

    • 可以知道HandlerThread继承于Thread,所以说HandlerThread本质上是一个线程,其构造方法主要是做一些初始化的操作。
    1
    2
    3
    4
    public HandlerThread(String name) {
    super(name);
    mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }

2.2 HandlerThread调用start方法

  • 调用了mHandlerThread.start()方法

    • 知道了HandlerThread类其实就是一个Thread,一个线程,所以其start方法内部调用的肯定是Thread的run方法,查看一下其run方法的具体实现:
    • 发现其内部调用了Looper.prepate()方法和Loop.loop()方法
    • 通过run方法,我们可以知道在我们创建的HandlerThread线程中我们创建了该线程的Looper与MessageQueue
    • 需要注意的是其在调用Looper.loop()方法之前调用了一个空的实现方法:onLooperPrepared(),我们可以实现自己的onLooperPrepared()方法,做一些Looper的初始化操作
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @Override
    public void run() {
    mTid = Process.myTid();
    Looper.prepare();
    synchronized (this) {
    mLooper = Looper.myLooper();
    notifyAll();
    }
    Process.setThreadPriority(mPriority);
    onLooperPrepared();
    Looper.loop();
    mTid = -1;
    }

2.3 创建对象接受消息

  • 代码如下所示:

    • Handler的构造方法中传入了HandlerThread的Looper对象,所以Handler对象就相当于含有了HandlerThread线程中Looper对象的引用。
    • 然后调用handler的sendMessage方法发送消息,在Handler的handleMessge方法中就可以接收到消息了。
    1
    2
    3
    4
    5
    6
    7
    // 创建的Handler将会在mHandlerThread线程中执行
    final Handler mHandler = new Handler(mHandlerThread.getLooper()) {
    @Override
    public void handleMessage(Message msg) {
    Log.i("tag", "接收到消息:" + msg.obj.toString());
    }
    };
  • 需要注意的是在不需要这个looper线程的时候需要手动停止掉;

    1
    2
    3
    4
    protected void onDestroy() {
    super.onDestroy();
    mHandlerThread.quit();
    }
  • 相对来说HandlerThread还是比较简单的,这里总结一下:

    • HandlerThread本质上是一个Thread对象,只不过其内部帮我们创建了该线程的Looper和MessageQueue;
    • 通过HandlerThread我们不但可以实现UI线程与子线程的通信同样也可以实现子线程与子线程之间的通信;
    • HandlerThread在不需要使用的时候需要手动的回收掉;

03.HandlerThread完整源码

  • 最后看一下HandlerThread 的完整源码注释

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    public class HandlerThread extends Thread {

    //线程优先级
    int mPriority;

    //线程ID
    int mTid = -1;

    //当前线程持有的Looper对象
    Looper mLooper;

    //包含当前 Looper 对象的 Handler
    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() {
    }

    @Override
    public void run() {
    mTid = Process.myTid();
    //触发当前线程创建 Looper 对象
    Looper.prepare();
    synchronized (this) {
    //获取 Looper 对象
    mLooper = Looper.myLooper();
    //唤醒在等待的线程
    //唤醒 getLooer() 中可能还处于等待状态的线程
    notifyAll();
    }
    //设置线程优先级
    Process.setThreadPriority(mPriority);
    onLooperPrepared();
    //开启消息循环
    Looper.loop();
    mTid = -1;
    }

    //获取与当前线程关联的 Looper 对象
    //因为 getLooper() 方法可能先于 run() 被调用,此时就需要先等待 Looper 对象被创建
    public Looper getLooper() {
    //如果当前线程未在运行,则返回 null
    if (!isAlive()) {
    return null;
    }
    synchronized (this) {
    //如果当前线程已处理运行状态(已调用 start() 方法)且 Looper 对象还未创建
    //则调用 wait() 方法释放锁,等待 Looper 对象创建
    while (isAlive() && mLooper == null) {
    try {
    wait();
    } catch (InterruptedException e) {
    }
    }
    }
    return mLooper;
    }

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

    //清空消息队列中所有的消息
    public boolean quit() {
    Looper looper = getLooper();
    if (looper != null) {
    looper.quit();
    return true;
    }
    return false;
    }

    //清空消息队列中所有非延时消息
    public boolean quitSafely() {
    Looper looper = getLooper();
    if (looper != null) {
    looper.quitSafely();
    return true;
    }
    return false;
    }

    /**
    * Returns the identifier of this thread. See Process.myTid().
    */
    public int getThreadId() {
    return mTid;
    }
    }