Android IntentService源码解析

        本文是对Android IntentService的源码解析,对其基本使用还不了解的朋友可以先快速入门IntentService再来阅读本文。

初始化

        类似于Activity,Service也有onCreate、onDestory等用于管理生命周期的方法,先来看看IntentService初始化的源码。

private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;

@Override
public void onCreate() {
        super.onCreate();
        //1
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

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

        IntentService是串行处理任务的,说到串行处理,Handler就是最典型的例子。从源码可以看出IntentService也用到了Handler。这里简单说一下Handler,Handler由如下几个部分组成。

HandlerThread:特殊的线程类,自带Looper,Handler必须运行在一个有Looper的线程上。
Looper:内部维护着一个消息队列,串行地取出消息进行处理。Looper是线程局部变量,也就是说每个HandlerThread都有属于自己的Looper(通过ThreadLocal来实现)。
Message:用于装载消息,消息传递完以后可以被Looper回收再利用(回收到Message池)。
MessageQueue:收到的消息在此排队等待Looper来处理。

        对Handler源码感兴趣的朋友可以看看我写的这篇文章。回到刚刚的源码,代码1先创建一个HandlerThread,这个线程就是IntentService处理请求的线程。代码2获取这个线程的Looper。代码3完成Handler初始化。

运行与停止

        完成了初始化操作,IntentService就可以来处理请求了。前面说到IntentService是通过Handler来串行处理请求的,来看看它的源码。

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的源码很简单,我们重写的onHandleIntent方法就是在handleMessage方法里调用的。处理完请求就尝试停止Service。也就是说调用stopSelf方法Service不一定会立刻停止。这里需要结合另外两个方法来解释。

@Override
public void onStart(@Nullable Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        //1
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
}
    
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        //2
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}

        看到代码1,刚刚stopSelf方法传入的startId就是来自这里。stopSelf方法会判断传入的startId和onStartCommand的startId是否相同。相同就停止服务,不相同就暂时不停止它。
        现在把onStartCommand的startId记为A,把stopSelf传入的startId记为B。A不等于B说明在任务1完成前,任务2请求就来了,如果完成了任务1立即停止服务,任务2的请求就不能得到处理了。同理,A等于B说明任务1完成时还没有新的任务请求发过来,这时立即停止服务并不会有什么不妥,新的任务请求发来了再重新启动服务就可以了,
        如此一来,IntentService就实现了自动停止的功能。接下来再看看服务停止时做了什么。

//IntentService.java
@Override
public void onDestroy() {
       mServiceLooper.quit();
}

//Looper.java
public void quit() {
        mQueue.quit(false);
}

        销毁服务的操作很简单,让Looper停下来就可以了,这里Looper是非安全退出,也就是说,队列里的任务会被取消掉。调用stopSelf(-1)不需要等所有的任务处理完,可以直接停止服务。

请求重传

IntentService有这么一个方法,它可以让Intent实现重传。

/**
     * Sets intent redelivery preferences.  Usually called from the constructor
     * with your preferred semantics.
     *
     * 

If enabled is true, * {@link #onStartCommand(Intent, int, int)} will return * {@link Service#START_REDELIVER_INTENT}, so if this process dies before * {@link #onHandleIntent(Intent)} returns, the process will be restarted * and the intent redelivered. If multiple Intents have been sent, only * the most recent one is guaranteed to be redelivered. * *

If enabled is false (the default), * {@link #onStartCommand(Intent, int, int)} will return * {@link Service#START_NOT_STICKY}, and if the process dies, the Intent * dies along with it. */ public void setIntentRedelivery(boolean enabled) { mRedelivery = enabled; } @Override public int onStartCommand(@Nullable Intent intent, int flags, int startId) { onStart(intent, startId); return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY; }

        注释里意思是说如果setIntentRedelivery方法传入true,那么在进程被杀死的时候,Intent会被保存下来,等进程重启了再重新发送这个Intent。但是,对于多个Intent只有那个最新的Intent能够重传。其实这是通过onStartCommand方法的返回值来实现的。

参考文章

    https://www.jianshu.com/p/5c1fae2794f6
    https://blog.csdn.net/mingli198611/article/details/8782772
    https://www.jianshu.com/p/63a644166013

你可能感兴趣的:(源码解析)