HandlerThread 原理分析

一、前言

HandlerThread 是什么,其实就是一个Thread子类,然后里面开启了一个Looper循环来处理handler 发送的消息。

为什么会有HandlerThread,我们都知道如果在子线程直接创建使用handler会报错,提示没有looper。我们必须自己调用

Looper.prepare()创建当前线程的Looper对象、Looper.loop()开启消息循环。不懂的可以看我另一篇文章:

https://blog.youkuaiyun.com/qq_32650001/article/details/99829747 安卓消息机制

但是这种方式太不人性化了,于是谷歌推出了HandlerThread ,里面自动Lopper 我们就可以愉快的在子线程里使用handler了。

二、HandlerThread的基本使用

  大致分为6步:

  1、创建 HandlerThread对象

  HandlerThread handlerThread = new HandlerThread("download")

  2、开启线程(为什么这个时候开启线程等会源码分析说)

  handlerThread.start()

  3、 构建循环消息处理机制(运行在子程序中)

  class ChildCallback implements Handler.Callback {
        @Override
        public boolean handleMessage(Message msg) {

            mUIHandler.sendMessage(msg1);
            //一般是主线程创建的handler对象去更新ui,mUIHandler的创建我没体现
            return false;
        }
    }

 4、创建绑定子线程的Handler对象

 Handler childHandler = new Handler(handlerThread.getLooper(),new ChildCallback());

 记住我们handlerThread.getLooper() 传入了子线程的Looper对象,此时改handler和子线程绑定到一起


 5、子线程handler发送消息

 childHandler.sendxxx(msg)

 6、结束线程,即停止线程的消息循环
 handlerThread.quit();

三、HandlerThread的源码分析

  HandlerThread源码很少,我们一起看看吧~

public class HandlerThread extends Thread {
    int mPriority;
    int mTid = -1;
    Looper mLooper;//Looper对象
    private @Nullable Handler mHandler;

    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }
    

    public HandlerThread(String name, int priority) {
        super(name);
        mPriority = priority;
    }
    

    protected void onLooperPrepared() {
    }


    /**
     * 上面我说了要先start,开启线程
     * 是因为开启线程后,会回调到run方法
     * 来创建我们的Looper对象并开启循环
     */
    @Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();//创建当前线程的Looper的对象
        synchronized (this) {
            mLooper = Looper.myLooper();//获取当前线程的Looper对象
            notifyAll();//发送通知
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();//开启循环
        mTid = -1;
    }
    


    /**
     * 还记得我们在代码中getLooper获取
     * 子线程的Looper给handler吧,你肯定会说
     * 如果Looper对象还没创建成功呢,我获取啥哦
     * 没事人家谷歌处理好了,请看~
     * 
     */
    public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }
        synchronized (this) {
            while (isAlive() && mLooper == null) {//如果当前Looper为null
                try {
                    wait()//等待,上面Looper创建好后会发送通知
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }

    @NonNull
    public Handler getThreadHandler() {
        if (mHandler == null) {
            mHandler = new Handler(getLooper());
        }
        return mHandler;
    }



    /**
     * 其实就是清空了MessageQueue中的消息
     */
    public boolean quit() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quit();
            return true;
        }
        return false;
    }

    /**
     * 先判断是否有正在处理的消息,有就处理,然后在清空MessageQueue中的消息
     */
    public boolean quitSafely() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quitSafely();
            return true;
        }
        return false;
    }

    public int getThreadId() {
        return mTid;
    }
}

四、总结:

上面分析了HandlerThread的使用和它的源码分析,算是比较清晰了,如果有什么不懂的地方欢迎给我留言,拜~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值