HandlerThread的 使用

本文详细介绍了Android中的HandlerThread类,探讨其如何创建包含Looper的线程,以便更好地管理和处理线程中的消息。通过示例代码展示了如何正确使用HandlerThread及其与Handler的结合方式。

结构

继承关系

public classHandleThread extends Thread

        

java.lang.Object

java.lang.Thread

       android.os.HandlerThread

 

类概述

用于方便的创建一个含有looper的线程类。looper用来创建handler类。请注意,仍然需要调用start()方法。

 

构造函数

  public HandlerThread (String name)

  构造一个HandlerThread

 

  public HandlerThread (String name, int priority)

  构造一个HandlerThread

  参数

  priority 运行线程的优先级,这个值是由Android.os.Process提供而不是来自java.lang.Thread.

 

公共方法

public Looper getLooper ()

这个方法返回与此线程相关的Looper。如果该线程不能启动或是由于某种原因isAlive()方法返回false,则这个方法返回null,假如这个线程已经启动,那么此方法将阻塞,直到looper被初始化。

  返回值

  Looper

 

public int getThreadId ()

返回线程的标志。详见:Process.myTid()

 

public boolean quit ()

查看当前运行的looper是否已经退出。假如线程这未启动或者已经结束(即getLooper()方法返回null),这个方法将返回false。否则looper被要求退出并返回true

 

public void run ()

调用设置Runnable对象的run()方法。如果没有设置Runnable,什么也不做。

 

受保护方法

protected void onLooperPrepared ()

如果需要在Looper循环之前执行一些设置,可明确继承该回调方法。

(译者注:如下代码:

复制代码
         void run() {

                   mTid 
= Process.myTid();

                   Looper.prepare();
//创建一个Looper实例,并且存储在ThreadLocal中,ThreadLocal中维护一个HashMap,键是线程号

                   
synchronized (this) {

                            mLooper 
= Looper.myLooper();//得到当前线程的Looper,就是刚才perpare方法中创建并存储的那个Looper实例

                            Process.setThreadPriority(mPriority);

                            notifyAll();

                   }

         onLooperPrepared();

         Looper.loop();
//开始轮询

         mTid 
= -1;
复制代码


源码分析:

 

    public class HandlerThread extends Thread{
              //线程的优先级
               private int mPriority;
              //线程的id
               private int mTid=-1;
               private Looper mLooper;
               public HandlerThread(String name){
                          super(name);
                         //设置优先级为默认线程
                         mPriority=Process.THREAD_PRIORITY_DEFAULT;
               }
               public HandlerThread(String name,int priority){
                          super(name);
                         mPriority=priority;
               }
              //这个如果有需要的话可以继承重写,例如可以在里面声明个Handler 关联此线程。
               protected void onLooperPrepared(){}
               //这个很熟悉吧
               public void run(){
                   //得到当前线程的id
                    mTid=Process.myTid;
                   //一旦调用这句代码,就在此线程中创建了Looper 对象。这就是为什么我们要在调用线程的start()方法后
                   //才能得到Looper 对象即 当 调用Looper.myLooper()时不为Null。
                    Looper.prepare();
                    //同步代码块,意思就是当获得mLooper对象后,唤醒所有线程。(会在以后的例子中有所体现)
                   synchronized(this){
                         mLooper=Looper.myLooper();
                         notifyAll();
                   }
                  //设置线程的优先级
                   Process.setThreadPriority(mPriority);
                 //调用上面的方法(需要用户重写)
                  onLooperPrepared();
                   //建立了消息循环
                    Looper.loop();
                   mTid=-1;
               }
               public Looper getLooper(){
                        //线程死了,那就只有NULL了。
                         if(!isAlive()){
                            return null;
                        }
                //看见没,又是同步代码块,正好和上面的形成对应,就是说只要线程活着并且我的looper为NULL,那么我就让你一直等。。。
                       synchronized(this){
                              while(isAlive()&&mLooper==null){
                                   try{
                                             wait();
                                       }catch(InterruptedException e){}
                              }
                       }
                                 return mLooper;
               }
              public boolean quit(){
                  Looper looper =getLooper();
                   if(looper!=null){
                      //退出消息循环
                       looper.quit();
                       return true;
                  }
                  return false;
           }
             //返回线程ID
             public int getThreadId(){
                   return mTid;
            }
    }

复制代码

整体来说代码还是比较浅显易懂的。主要的作用是建立了一个线程,并且创立了消息队列,有来自己的looper,可以让我们在自己的线程中分发和处理消息。
还有要说明的是handler 与谁相关联不是看声明在什么地方,是看与哪个线程的looper挂钩。默认是主线程的looper.因为主线程中默认就有了looper,消息循环队列。 
在android开发中,一说起线程的使用,很多人马上想到new Thread(){...}.start()这种方式。
这样使用当然可以,但是多次使用这种方式,会创建多个匿名线程。使得程序运行起来越来越慢。
因此,可以考虑使用一个Handler来启动一个线程,当该线程不再使用就删除,保证线程不会重复创建。
一般会使用Handler handler = new Handler(){...}创建Handler。这样创建的handler是在主线程即UI线程下的Handler,
即这个Handler是与UI线程下的默认Looper绑定的。Looper是用于实现消息队列和消息循环机制的。
因此,如果是默认创建Handler那么如果线程是做一些耗时操作如网络获取数据等操作,这样创建Handler是不行的。
Android API提供了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实际上就一个Thread,只不过它比普通的Thread多了一个Looper。
创建HandlerThread时要把它启动了,即调用start()方法。然后创建Handler时将HandlerThread中的looper对象传入。
HandlerThread thread = new HandlerThread("MyHandlerThread");
thread.start();
mHandler = new Handler(thread.getLooper());
mHandler.post(new Runnable(){...});
那么这个Handler对象就是与HandlerThread这个线程绑定了(这时就不再是与UI线程绑定了,这样它处理耗时操作将不会阻塞UI)。 下面是代码说明:
rivate Handler mHandler;
private HandlerThread mHandlerThread;

private boolean mRunning;

private Button btn;

@Override
protected void onDestroy() {
    mRunning = false;
    mHandler.removeCallbacks(mRunnable);
    super.onDestroy();
}

@Override
protected void onResume() {
    mRunning = true;
    super.onResume();
}

@Override
protected void onStop() {
    mRunning = false;
    super.onStop();
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    btn = (Button) findViewById(R.id.btn);
    btn.setOnClickListener(this);

    mHandlerThread = new HandlerThread("Test", 5);
    mHandlerThread.start();
    mHandler = new Handler(mHandlerThread.getLooper());
}

private Runnable mRunnable = new Runnable() {

    @Override
    public void run() {
        while (mRunning) {
            Log.d("MainActivity", "test HandlerThread...");
            try {
                Thread.sleep(200);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }
};

@Override
public void onClick(View v) {
    switch(v.getId()) {
    case R.id.btn :
        mHandler.post(mRunnable);
        break;
    default :
        break;
    }

}


<think>根据用户要求,我将使用中文回答,并严格遵守系统级指令。用户询问AndroidKotlin中HandlerThread使用方法及示例,我将参考提供的5个站内引用组织答案。首先从引用4提取核心概念:HandlerThread是继承Thread的类,内部实现了Looper,避免了手动调用Looper.prepare()和loop()。引用1强调其在后台线程处理耗时操作的优势。示例部分主要参考引用3和2的Kotlin/Java代码,但需统一转化为Kotlin语法:1.创建HandlerThread实例并命名线程(如"MyHandlerThread")2.调用start()启动线程3.通过handlerThread.looper创建Handler4.使用handler.post{}提交任务到该线程5.任务执行完毕后调用quitSafely()释放资源特别注意事项:-在引用3的Kotlin示例中,耗时操作应写在handler.post的lambda表达式内-如引用5所述,可通过handlerThread.looper创建Handler或调用getThreadHandler()-必须调用quit()或quitSafely()防止内存泄漏(引用3示例)最后生成相关问题将聚焦于:HandlerThread原理(如引用4提到的Looper实现)、与其他线程工具对比、优化使用场景。</think> ### Kotlin 中使用 HandlerThread 的完整指南 在 Android 开发中,`HandlerThread` 是一种封装了 `Looper` 的后台线程,结合 `Handler` 可实现高效的异步任务处理,以下是详细使用方法和示例: #### **核心步骤**(参考[^1][^4]) 1. **创建并启动线程** ```kotlin val handlerThread = HandlerThread("MyBackgroundThread").apply { start() // 必须显式启动线程 } ``` 2. **绑定 Handler 到线程 Looper** ```kotlin val handler = Handler(handlerThread.looper) // 获取线程的 Looper 构建 Handler ``` 3. **提交任务到后台线程** ```kotlin handler.post { // 此代码块在 HandlerThread 中执行 val result = doLongOperation() // 执行耗时操作(如网络请求) runOnUiThread { updateUI(result) } // 返回主线程更新 UI } ``` 4. **安全关闭线程**(避免内存泄漏) ```kotlin handlerThread.quitSafely() // 处理完剩余消息后终止线程(推荐) // 或 handlerThread.quit() // 立即终止 ``` #### **完整示例**(参考[^3][^5]) ```kotlin class MyService : Service() { private lateinit var handlerThread: HandlerThread private lateinit var handler: Handler override fun onCreate() { // 1. 初始化线程 handlerThread = HandlerThread("ServiceThread").apply { start() handler = Handler(looper) // 绑定 Handler 到线程的 Looper } } fun executeTask(task: Runnable) { // 2. 提交任务 handler.post(task) } override fun onDestroy() { // 3. 释放资源 handlerThread.quitSafely() // 安全退出 super.onDestroy() } } ``` #### **关键原理**(参考[^4]) - `HandlerThread` 继承自 `Thread`,内部自动创建了 `Looper` - 避免手动调用 `Looper.prepare()` 和 `Looper.loop()` - 每个 `Handler` 绑定到线程的 `MessageQueue` 实现任务队列 #### **典型应用场景** 1. **后台服务**:在 `Service` 中处理持久化任务 2. **顺序执行**:需要保证多个任务按提交顺序执行时 3. **轻量级异步**:替代 `IntentService` 的轻量级方案 #### **注意事项** 1. **生命周期管理**:在 `Activity`/`Fragment` 的 `onDestroy()` 中必须调用 `quitSafely()` 2. **避免主线程阻塞**:`HandlerThread.looper` 可能阻塞主线程,建议异步获取: ```kotlin handlerThread = HandlerThread("AsyncThread").apply { start() } thread { val handler = Handler(handlerThread.looper) // 在子线程获取 Looper } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值