Moosphan/Android-Daily-Interview

2019-04-24:HandlerThread 的使用场景和用法?

Moosphan opened this issue · 15 comments

2019-04-24:HandlerThread 的使用场景和用法?

HandlerThread 是 Android 封装的一个线程类,将 Thread 跟 Handler 封装。使用步骤如下:

  1. 创建 HandlerThread 实例对象
    HandlerThread mHandlerThread = new HandlerThread("mHandlerThread");
  1. 启动线程
    mHandlerThread .start();
  1. 创建Handler对象,重写handleMessage方法
    Handler mHandler= new Handler( mHandlerThread.getLooper() ) {
           @Override
           public boolean handleMessage(Message msg) {
               //消息处理
               return true;
           }
     });
  1. 使用工作线程Handler向工作线程的消息队列发送消息:
     Message  message = Message.obtain();
     message.what = “2message.obj = "*风"
     mHandler.sendMessage(message);
  1. 结束线程,即停止线程的消息循环
     mHandlerThread.quit();

HandlerThread=Handler+Thread,是一个非常方便的封装类,要注意的是HandlerThread不会自动停止,必须手动调用quit()方法。
关于使用场景,我一般都是开一个HandlerThread当全局的工作线程处理那些杂物(而且我会设置为守护线程,同时把优先级调成背景线程),比如不重要的文件读写操作直接扔给这个线程,免得卡主线程。至于怎么用楼上已经说的很清楚了,不再赘述。

来了 我居然一直没用过HandlerThread
去瞅两眼

HandlerThread继承Thread是一个线程类。
我们可以使用HandlerThread处理本地IO读写操作(数据库,文件),因为本地IO操作大多数的耗时属于毫秒级别,对于单线程 + 异步队列的形式 不会产生较大的阻塞

HandlerThread 本质上是一个在子线程的handler (HandlerThread=Handler+Thread);
它的使用:
步骤1:创建HandlerThread实例对象
HandlerThread mHandlerThread = new HandlerThread("handlerThread");
步骤2:启动线程
mHandlerThread.start();
步骤3:创建工作线程Handler & 复写handleMessage()
Handler workHandler = new Handler( handlerThread.getLooper() ) {
@OverRide
public boolean handleMessage(Message msg) {
...//消息处理
return true;
}
});
步骤4:使用工作线程Handler向工作线程的消息队列发送消息
Message msg = Message.obtain();
msg.what = 2; //消息的标识
msg.obj = "B"; // 消息的存放
// b. 通过Handler发送消息到其绑定的消息队列
workHandler.sendMessage(msg);

步骤5:结束线程,即停止线程的消息循环
mHandlerThread.quit();

优势:
1.将loop运行在子线程中处理,减轻了主线程的压力,使主线程更流畅
2.串行执行,开启一个线程起到多个线程的作用
3.有自己的消息队列,不会干扰UI线程
劣势:
1.由于每一个任务队列逐步执行,一旦队列耗时过长,消息延时
2.对于IO等操作,线程等待,不能并发

IntentService就是由HandlerThread实现的

HandlerThread其实是Handler+thread,在内部的实现方法中就是通过获取thread的looper,来初始化Handler,HandlerThread的使用可以参考IntentService

HandlerThread 是一个工具类。一些异步任务场景中,我们需要在子线程发消息,主线程处理消息,这种时候就需要 Thread+Handler+Looper 的组合。

Thread 负责执行耗时任务操作,Handler 负责在异步任务过程中发送消息,在子线程中使用 Handler 发送消息时,需要绑定一个子线程中的 Looper 对象,所以执行线程 run 方法时,需要去构造一个 looper 对象,并启用 loop,然后把 looper 传递给 Handler 的构造方法。

new Thread() {
  @Override
  public void run() {
    super.run();
    Looper.prepare();
    Looper looper = Looper.myLooper();
    mHandler = new Handler(looper);
    Looper.loop();
  }
}.start();

因为开发中,经常有这样的单线程+异步任务场景,所以 Android 提供了工具类 HandlerThread,把上面的操作更严密的做了封装。

HandlerThread 继承自 Thread,跟其它线程不一样,它自带一个 Looper,同时提供一个创建 Handler 的方法,该 Handler 使用 HandlerThread 中创建的 looper,最终就是一个 HandlerThread 创建后,会对应一个单独的 Looper 跟对应的 Handler。

主线程处理消息

不应该是新开的子线程处理消息,主线程发送消息吗?

主线程处理消息

不应该是新开的子线程处理消息,主线程发送消息吗?

异步任务都是子线程发消息,然后在主线程处理啊~ 我觉得我们认为的消息类型可能不一样。

HandlerThread 继承自 Thread , 它是一种可以使用 handler 的 Thread, 就是 在run 方法中通过 Looper.prepare 来创建消息队列,并通过 Looper.loop() 来开启消息循环。

普通 Thread 主要用于在 run 方法中执行一个耗时任务,而 HandlerThread 内部创建了消息队列,外界需要通过 Handler 的消息方式来通知 HandlerThread 执行具体任务。HandlerThread 的具体使用场景是 IntentService。IntentService 封装了 HandlerThread 和 Handler 。HandlerThread 主要用来处理需要顺序执行的异步操作。

由于 HandlerThread 的 run 是一个无线循环,因此当明确不需要 HandlerThread 时可以通过 quit 或 quitSafely 来终止线程的执行。

使用方法:

  1. 创建 HandlerThread 对象,并调用 start 方法启动。
  2. 使用 HandlerThread 获取 Looper,用 Looper 创建 Handler 。
  3. 使用 handler 发送消息,并在 处理消息。
  4. 不再使用时终止线程。

带有消息循环的thread

com.orhanobut.logger就是HandlerThread 实现的

HandlerThread继承于Thread 是一个线程类 在run方法中通过Looper.prepare来创建消息队列并通过Looper.loop()来开启消息循环 通过创建HandlerThread来启动一个子线程的Handler来做一些耗时操作 比如数据查询
完成后可创建一个UI线程的Handle来做界面更新