Android 中的 HandlerThread 类详解

简介

HandlerThread 类继承至 Thread 类,你可以把它看做是一个普通的线程类;当然,既然我们今天要说它,就不能在把它看做是一个普通的线程类了类处理了。HandlerThread 类与普通的线程类的主要区别就是:重写 run() 方法,并且创建了一个属于自己线程包含消息队列 Looper 对象;同时提供了 getLooper() 方法给外界获取 Looper 对象。

好处

  1. 开发中如果多次使用类似 new Thread(){...}.start() 这种方式开启一个子线程,会创建多个匿名线程,难于管理且使得程序运行起来越来越慢,而 HandlerThread 自带 Looper 包含一个独立的队列使它可以通过消息来多次重复使用当前线程,节省开支;
  2. 既然 HandlerThread 自带包含队列的 Looper ,那么它就可以分担主线程的 Looper 队列的压力;
  3. Android系统提供的 Handler 类内部的 Looper 默认绑定的是UI线程的消息队列,对于非UI线程又想使用消息机制,那么 HandlerThread 内部的 Looper 是最合适的,它不会干扰或阻塞UI线程。

使用方式

private HandlerThread handlerThread; // HandlerThread 对象
private Handler workHandler; // 工作线程的Handler对象
private Handler uiHandler = new Handler() { // 主线程/UI线程 的Handler对象
    @Override
    public void handleMessage(Message msg) {
        Toast.makeText(MainActivity.this, "接收到刷新界面的消息: " + msg.what, Toast.LENGTH_SHORT).show();
    }
};

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

    handlerThread = new HandlerThread("handler_thread_test");
    handlerThread.start();
    // handlerThread.quit(); // 退出

	// 创建工作线程的Handler对象
    workHandler = new Handler(handlerThread.getLooper()) {
        @Override
        public void handleMessage(Message msg) {
            // 模拟耗时操作
            SystemClock.sleep(msg.arg1);
            Log.i("MainActivity", "Thread: " + Thread.currentThread().getName());
            // 发送刷新界面消息
            uiHandler.sendEmptyMessage(msg.what);
        }
    };

    Message message;
    for (int i = 1; i <= 3; i++) {
        message = Message.obtain();
        message.what = i;
        message.arg1 = 1000 * i;
        // 将 Message 对象发送到工作线程
        workHandler.sendMessage(message);
    }
}

源码解析

1.构造方法

// 指定线程名称
public HandlerThread(String name) {
	super(name);
	mPriority = Process.THREAD_PRIORITY_DEFAULT; // 优先级 0
}

// 指定线程名称和优先级 优先级:-19 ~ 19 ,19 表示优先级最低;默认 0
public HandlerThread(String name, int priority) {
	super(name);
	mPriority = priority;
}

2.初始化方法,按需重写

protected void onLooperPrepared() {
}

默认空实现,用于开启轮询前进行初始化。

3.getLooper() 方法

public Looper getLooper() {
	// 判断线程状态
    if (!isAlive()) {
        return null;
    }
    
    // If the thread has been started, wait until the looper has been created.
	// 如果线程已经启动,等待 Looper 创建完成
    synchronized (this) {
        while (isAlive() && mLooper == null) {
			// 如果线程是正在运行状态但是 mLooper 对象为 null,线程等待
			// 提前说明一下,是在 run() 方法中唤醒的
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
    }
    return mLooper;
}

4.run()方法

@Override
public void run() {
	mTid = Process.myTid();
	// 调用 Looper.prepare() 方法,将线程变为 Looper 线程
	Looper.prepare();
	synchronized (this) {
		// 获取当前线程的 Looper 对象
		mLooper = Looper.myLooper();
		// 唤醒线程,wait() 等待方法在 getLooper() 方法中调用
		notifyAll();
	}
	// 设置线程优先级
	Process.setThreadPriority(mPriority);
	// 回调初始化方法
	onLooperPrepared();
	// 启动轮询器,开始对消息队列进行轮询
	Looper.loop();
	mTid = -1;
}

5.结束方法

// 调用 looper.quit() 退出,清除全部消息(包括延时消息和非延时消息)
public boolean quit() {
	Looper looper = getLooper();
	if (looper != null) {
		looper.quit();
		return true;
	}
	return false;
}

// 调用 looper.quitSafely() 退出,清除所有的延时消息,把所有非延时消息进行发送
public boolean quitSafely() {
	Looper looper = getLooper();
	if (looper != null) {
		looper.quitSafely();
		return true;
	}
	return false;
}

6.其他方法

// 获取当前线程的 Handler 对象
public Handler getThreadHandler() {
    if (mHandler == null) {
        mHandler = new Handler(getLooper());
    }
    return mHandler;
}

// 获取当前线程 id
public int getThreadId() {
    return mTid;
}

HandlerThread 类源码非常简单,就是在普通的线程中创建了一个 Looper 对象使之变为了一个 Looper 线程。类的源码说明在注释上面已经非常清晰,就不在重复了。

总结

  • HandlerThreadLooper 转到子线程中处理,分担了 MainLooper 的工作量,降低了主线程的压力,使主界面更流畅;
  • 开启一个线程起到多个线程的作用。处理任务是串行执行,按消息发送顺序进行处理。HandlerThread 本质是一个线程,在线程内部,代码是串行处理的
  • 由于每一个任务都将以队列的方式逐个被执行到,一旦队列中有某个任务执行时间过长,那么就会导致后续的任务都会被延迟处理;
  • HandlerThread 拥有自己的消息队列,它不会干扰或阻塞UI线程;
  • 对于网络操作,HandlerThread 并不适合,因为它只有一个线程,延时可能比较严重。

HandlerThread 在Android中的应用

《Android 中的 IntentService 类详解》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值