HandlerThread原理分析

要想在非ui线程中使用handler,我们首先想到的是那三大步,Looper.prepare(),创建 handler,Looper.loop(),必要时还要quit一下,这种方法虽合情合理,但总让人感觉丑陋且繁琐,这时候HandlerThread就应运而生了。

使用方式

IntentService为我们完美展示了HandlerThread的使用方式:

	private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
        }
    }
	//创建HandlerThread并开启
	HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
    thread.start();
	//创建handler并传入HandlerThread维护的Looper
    mServiceLooper = thread.getLooper();
    mServiceHandler = new ServiceHandler(mServiceLooper);
	//发送消息
	Message msg = mServiceHandler.obtainMessage();
    msg.arg1 = startId;
    msg.obj = intent;
    mServiceHandler.sendMessage(msg);
    //及时销毁
	public void onDestroy() {
        mServiceLooper.quit();
    }

原理分析

由于HandlerThread源码很简单,所以直接贴出附注释:

public class HandlerThread extends Thread {
    int mPriority;
    int mTid = -1;
    Looper mLooper;
    private @Nullable Handler mHandler;
	
	//构造方法1
	//设置线程名称,并为线程设置默认优先级
    public HandlerThread(String name) {
        super(name);
        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
        Looper.prepare();
        //使用锁和notifyAll保证getLooper()一定能获取到Looper对象
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        //设置线程优先级
        Process.setThreadPriority(mPriority);
        //准备工作
        onLooperPrepared();
        //开启循环
        Looper.loop();
        //释放线程id
        mTid = -1;
    }
    
   
    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) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }

    /**
     * @return a shared {@link Handler} associated with this thread
     * @hide
     */
    @NonNull
    public Handler getThreadHandler() {
        if (mHandler == null) {
            mHandler = new Handler(getLooper());
        }
        return mHandler;
    }

   	//停止消息循环,非线程安全
    public boolean quit() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quit();
            return true;
        }
        return false;
    }

	//停止消息循环,线程安全 API Level 18   
    public boolean quitSafely() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quitSafely();
            return true;
        }
        return false;
    }

    /**
     * Returns the identifier of this thread. See Process.myTid().
     */
    public int getThreadId() {
        return mTid;
    }
}

总结

可以看到,HandlerThread内部也是由handler和Thread封装而成,我们不仅要学习其原理,还要学习它封装的思想,上面源码中getLooper()和run()是异步进行,为了防止获取到的looper为空,使用了wait()进行等待,等looper.myLooper执行结束后再将其唤醒,从而保证在线程存活的情况下一定能getLooper()。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值