HandlerThread

2021-03-28  本文已影响0人  编程的猫

在分析HandlerThread的源码之前,可以先大致看一下HandlerThread的源码有哪些东西

public class HandlerThread extends Thread {
    // 线程优先级
    int mPriority;
    // 线程的ID
    int mTid = -1;
    // 详细循环器
    Looper mLooper;
    // 消息处理器
    private @Nullable Handler mHandler;

    // 构造方法1,参数是设置线程的名称
    public HandlerThread(String name) {
        super(name);
        // 设置线程的默认优先级 0
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }
    
    // 构造方法2 :线程名称,优先级
    public HandlerThread(String name, int priority) {
        super(name);
        mPriority = priority;
    }
    
    protected void onLooperPrepared() {
    }

    @Override
    public void run() {
        // 获取线程的Id
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }
    
    public Looper getLooper() {
        // 判断线程是否存活
        if (!isAlive()) {
            return null;
        }
        
        // If the thread has been started, wait until the looper has been created.
        // 如果线程已经创建,直到looper创建完成返回looper
        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }

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

    // 退出looper消息循环
    public boolean quit() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quit();
            return true;
        }
        return false;
    }

    // 安全退出looper的消息循环,与quit()的区别是会执行完队列中所有的消息,然后再退出
    public boolean quitSafely() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quitSafely();
            return true;
        }
        return false;
    }

    // 获取线程的额ID
    public int getThreadId() {
        return mTid;
    }
}

通过源码可以看到HandlerThread继承自Thread(说明他是一个线程),在其内部实现了Looper,说明具有发送和接收消息的功能,可以实现线程间的通信。

也就是说,如果需要创建一个线程执行耗时任务并与其他线程进行通信的场景,就可以使用HandlerThread

那么要搞明白HandlerThread就要先清楚Looper。Looper的分析请查看这篇文章

HandlerThread如何执行一个耗时任务?

答案:在绑定HandlerThread的handler的handleMessage回调中可以执行耗时任务

使用示例:(子线程与子线程通信)

// 测试HandlerThread
private void testHThread() {
    HandlerThread testHandlerThread = new HandlerThread("testHandlerThread");

    // 启动Thread
    testHandlerThread.start();

    // 给Handler指定绑定的线程,并覆写handleMessage方法
    Handler workHandler = new Handler(testHandlerThread.getLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);

            // 判断这个回调是不是在主线程,在该回调可以执行耗时任务

            boolean isMain = Looper.myLooper() == Looper.getMainLooper();
            boolean isEquals = testHandlerThread.getLooper() == Looper.myLooper();
            Log.d("iCat", "收到消息=====>    是否主线程" + isMain + "  isEquals:" + isEquals);


            try {
                Thread.sleep(3000);
                // 这里执行更新UI的操作会崩掉,因为这个回调是在子线程中调用的
                iv.setImageResource(R.mipmap.ic_launcher);

                tv.setText("你是一个好人");

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };

    // 这里演示子线程给子线程发送消息
    new Thread(new Runnable() {
        @Override
        public void run() {
            // 使用工作线程向工作线程发送消息
            Message message = Message.obtain();
            message.what = 1;
            message.obj = "测试数据";
            workHandler.sendMessage(message);

            Log.d("iCat", "发送消息====>    currentThread: " + Thread.currentThread());

        }
    }).start();

}

总结

HandlerThread实际上就是Thraed加Handler的组合封装,系统提供的一种子线程执行耗时任务与其他线程通信的一种便捷方式。

上一篇下一篇

猜你喜欢

热点阅读