android Thread线程—HandlerThread

发布于:2025-09-05 ⋅ 阅读:(12) ⋅ 点赞:(0)

Android 消息机制就是 典型的「生产者-消费者」实现;而 HandlerThread 正是官方提供的“后台消费者线程”——内部自带 Looper/MessageQueue,让你只关心「生产消息」即可。下面把原理、用法和完整代码一次性给你。

HandlerThread 五步曲

// 1. 创建并启动
HandlerThread ht = new HandlerThread("bg-thread");
ht.start();

// 2. 拿到 Looper 建 Handler(消费者)
Handler bgHandler = new Handler(ht.getLooper()) {
    @Override public void handleMessage(Message msg) {
        // 在后台线程执行耗时任务
        doHeavyWork(msg.obj);
        // 完成后可回调主线程
        uiHandler.obtainMessage(MSG_DONE, msg.obj).sendToTarget();
    }
};

// 3. 任意线程生产消息
bgHandler.sendMessage(bgHandler.obtainMessage(0, data));

// 4. 主线程更新 UI
Handler uiHandler = new Handler(Looper.getMainLooper()) {
    @Override public void handleMessage(Message msg) {
        updateUI(msg.obj);
    }
};

// 5. 退出循环(Activity/Fragment 销毁时)
ht.quitSafely();

HandlerThread源码
 

public class HandlerThread extends Thread {

    /**
     * 线程真正开始执行时的入口。
     * 作用:为当前子线程创建 Looper,并让外部线程可以安全拿到这个 Looper。
     */
    public void run() {
        mTid = Process.myTid();           // 记录当前线程的 Linux tid,方便调试

        Looper.prepare();                 // 1. 创建 Looper 并绑定到当前线程(ThreadLocal)

        synchronized (this) {             // 2. 同步块:防止并发获取 Looper 时出现竞态
            mLooper = Looper.myLooper();  // 3. 把刚建好的 Looper 保存到成员变量
            notifyAll();                  // 4. 唤醒所有在 getLooper() 中 wait() 的线程
        }

        Process.setThreadPriority(mPriority); // 5. 设置线程优先级(如 BACKGROUND)
        onLooperPrepared();                   // 6. 空方法,子类可重写做初始化工作
        Looper.loop();                        // 7. 开始无限循环:取消息 → 分发 → 处理
        mTid = -1;                            // 8. 循环退出后,清掉 tid 标记
    }

    /**
     * 供外部线程调用,获取与本线程关联的 Looper。
     * 如果线程尚未启动或 Looper 还没准备好,会阻塞等待。
     */
    public Looper getLooper() {
        if (!isAlive()) {          // 线程根本没 start → 直接返回 null
            return null;
        }

        boolean wasInterrupted = false;   // 记录等待过程中是否被中断

        // 线程已启动,但 Looper 可能还没创建好 → 需要等待
        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();               // 等待 run() 里 notifyAll()
                } catch (InterruptedException e) {
                    wasInterrupted = true; // 捕获中断,稍后恢复标志
                }
            }
        }

        // 如果在 wait() 时被中断,需要把中断状态“补”回去
        if (wasInterrupted) {
            Thread.currentThread().interrupt();
        }

        return mLooper;   // 此时 mLooper 一定非 null(除非线程已退出)
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到