Android多线程之HandlerThread在IntentService中的应用

HandlerThread

 HandlerThread 继承 Thread,是一种可以使用 Handler 的 Thread ,它的具体实现,就是在 run 方法中通过 Looper.prepare() 来创建消息队列,并通过 Looper.loop() 来开启消息循环。run 方法具体代码实现如下:

    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }

    从HandlerThread 的 run 方法实现来看,与普通的 Thread 会有一些不同。普通的 Thread 的 run 方法中主要是执行一些耗时的任务,而 HandlerThread 的 run 方法中,是创建一个消息队列,外界需要通过 Handler 的发送消息的方法来通知 HandlerThread 方法执行任务。由于 HandlerThread 的 run 方法是一个无限循环,所以当不再使用 HandlerThread 的情况下,记得调用它的 quit 或者 quitSafely 方法来终止线程的执行。

    HandlerThread 的一个非常重要的使用场景,就是 IntentService。

IntentService

    IntentService 是一个特殊的 Service,是一个抽象类,继承与Service,所以当使用它的时候,需要创建它的子类。IntentService 一般用于执行一些后台的耗时任务,当任务执行完毕后它会自动停止。而且由于 IntentService 是一个 Service,它的优先级会比一般的线程要高得多,所以非常适合执行一些优先级较高的后台任务。

    IntentService 内部封装了 HandlerThread 和 Handler,来看看它的 onCreate 方法就可以看出:
    public void onCreate() {
        // TODO: It would be nice to have an option to hold a partial wakelock
        // during processing, and to have a static startService(Context, Intent)
        // method that would launch the service & hand off a wakelock.

        super.onCreate();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

    从上面代码可以看出,当 IntentService 第一次启动的时候,回去创建一个 HandlerThread 对象,然后使用它的 Looper 来构造一个 Handler 对象,所以通过 mServiceHandler 发送消息最终都会走到 HandlerThread 这里来执行。我们先来看看  mServiceHandler mServiceHandler 是 IntentService 的一个静态内部类,代码如下:
    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);
        }
    }

    从ServiceHandler 的 handlerMessage 方法可以看出,当执行完 IntentService 的 onHandlerIntent 方法后,会调用 stopSelf 方法来终止。而 onHandlerIntent 方法,是我们在 IntentService 的子类中需要重写的方法,通过传进来的 Intent 来区分不同的后台任务,从而做不同的处理。
   再来看看 IntentService 的 onStartCommand 方法,因为每次启动 IntentService 的时候,都会执行一次 onStartCommand 方法,而  onStartCommand 里直接调用 onStart 方法,我们来看看 onStart 方法的代码:
    public void onStart(@Nullable Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }
   这样就能看出来了,onStart 方法里面,就通过 mServiceHandler 的 sendMessage(msg) 方法发送消息,然后到 ServiceHandler 中的 handlerMessage 中来处理。
    我们就来总结下通过 startService 来启动一个 IntentService 的具体流程:
        startService(IntentService) -> IntentService.onCreate() -> onStartCommand() -> onStart() -> ServiceHandler.handlerMessage() -> IntentService.onHandlerIntent()

为什么 IntentService 内部要使用 HandlerThread 呢?
我的理解是:IntentService 这样的设计,是为了让多个后台任务能够有序的执行。因为 HandlerThread 是每次只处理一个任务,处理完了在处理下一个任务的。如果 IntentService 不使用 HandlerThread ,而是直接 new Thread ,就变成了多个线程执行了,达不到按顺序执行的效果了。


整篇博文都是通过阅读 Android 开发艺术探索 而对自己的学习总结,如想更深入的了解,建议直接读该书!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值