Android中IntentService实现原理详解

写在前头:近期或多或少的去了一些比较优秀的企业面试,现在的企业要求比较高,当然也可能和你面试的岗位有关,一定的工作年限需要有对应的知识的深度和宽度,并且会发现一个特性,就是面试官非常注重你的基础知识的理解和掌握能力,比如说去面试Android开发,但是可能会问你很多的java知识,包括Http和Https,还有网络通信,H5数据交互等等知识点,那么我们应该如何应对这些呢,答案只有一个,多看多理解多积累,毕竟咱们这一行速成容易,精通很难,所以这就是为什么实际工作过的攻城狮和培训出来的人最直接的区别,一个是精通原理,一个是掌握使用方法,在现在这个阶段,优秀的企业挑选的只会是掌握原理的人,哪怕不会用到,但是这代表了一个攻城狮的自我修养,自己的学习能力,自己的钻研能力,好了,写到这儿,我会写一系列的面试知识点整理,也就是我遇到的一些比较有意思的东西,和大家分享,开始吧!

想起看这个的源码是因为上次被人家问到了,IntentService中的onHandlerIntent()在什么时候被回调的,说实话我没看过,但是根据它这个方法名的回调我猜肯定是在handler中进行回调的,虽然说没有死问到底,但是出于一个求知的心态,我们应该还是需要知道IntentService底层是如何工作的,所以我们今天一起来看看这个东西吧,源码不多,也容易看懂,一起来过一遍。

首先来上一段源码,在其中打补丁写详细的注释~

/**
* IntentService是一种特殊的Service,它继承于Service并且还是个抽象类
* 所以我们必须创建它的子类才能使用IntentService
* IntentService可以用来执行后台任务,当任务执行完后就会“自杀”
* 因为它自己也是个服务,所以优先级高于普通的线程,不容易被系统所干掉
* 所以IntentService比较适合执行优先级较高的后台任务
*/
public abstract class IntentService extends Service {
    //HandlerThread的looper
    private volatile Looper mServiceLooper;
    //通过looper创建的一个Handler对象,用于处理消息
    private volatile ServiceHandler mServiceHandler;
    private String mName;
    private boolean mRedelivery;

    /**
    * 通过HandlerThread线程中的looper对象构造的一个Handler对象
    * 可以看到这个handler中主要就是处理消息
    * 并且将我们的onHandlerIntent方法回调出去
    * 然后停止任务,销毁自己
    */
    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            /**
            * 收到消息后,会将Intent对象传递给onHandlerIntent方法去处理
            * 注意这个Intent对象的内容和外界Activity中startService(intent)
            * 中的intent的内容是完全一致的
            * 通过这个intent对象可以得到外界启动IntentService时所传递的参数
            * 通过这些参数我们就可以区分不同的业务逻辑
            * 这样onHandlerIntent就可以对不同的逻辑做出不同的操作了
            * 当onHandlerIntent方法执行结束后,IntentService会通过
            * stopSelf(int startId)方法尝试停止服务
            * 之所以使用stopSelf(int startId)而不是stopSelf()来停止
            * 是因为stopSelf()会马上停止服务,但是有可能还有消息未处理
            * stopSelf(int startId)则会等所有的消息都处理完后才销毁自己
            * 一般来说的话,stopSelf(int startId)在停止之前会判断
            * 最近启动服务的次数和startId是不是相等的,如果相等就立刻停止
            * 如果不相等说明还有别的消息没处理,就不停止服务
            * 具体的要看AMS中的stopServiceToken方法的实现
            */
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
        }
    }

    /**
    * 构造函数,可以传递一个name参数
    */
    public IntentService(String name) {
        super();
        mName = name;
    }

    public void setIntentRedelivery(boolean enabled) {
        mRedelivery = enabled;
    }

    /**
    * 当我们的IntentService第一次启动的时候,onCreate方法会执行一次
    * 可以看到方法里创建了一个HandlerThread
    * HandlerThread继承Thread,它是一种可以使用Handler的Thread
    * 它的run方法里通过Looper.prepare()来创建消息队列
    * 并通过Looper.loop()来开启消息循环,所以就可以在其中创建Handler了
    * 这里我们通过HandlerThread得到一个looper对象
    * 并且使用它的looper对象来构造一个Handler对象,就是我们上面看到的那个
    * 这样做的好处就是通过mServiceHandler发出的消息都是在HandlerThread中执行
    * 所以从这个角度来看,IntentService是可以执行后台任务的
    */
    @Override
    public void onCreate() {
        super.onCreate();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

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

    /**
    * 这个方法里的实现其实就很简单了,就是通过handler发送了一个消息
    * 把我们的intent对象和startId发送出去
    * 在我们上面的handleMessage()会接收到消息
    * 并且通过onHandlerIntent()方法将对象回调给子类
    */
    @Override
    public void onStart(@Nullable Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }

    /**
    * 每次启动IntentService,onStartCommand()就会被调用一次
    * 在这个方法里处理每个后台任务的intent
    * 可以看到在这个方法里调用的是上方的onStart()方法
    */
    @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

    /**
    * 因为looper是无限循环轮询消息的一个机制,所以当我们明确不需要继续使用的话
    * 那么我们就应该通过它的quit()方法来终止它的执行
    * 这是个编程的好习惯,要记住哦!
    */
    @Override
    public void onDestroy() {
        mServiceLooper.quit();
    }

    /**
    * 这个方法的注释写了:除非你为这个service提供了绑定,否则不需要实现这个方法
    * 因为这个方法默认是返回null的
    * 所以咱们不用太关注这个方法
    */
    @Override
    @Nullable
    public IBinder onBind(Intent intent) {
        return null;
    }

    /**
    * 这就是IntentService中定义的抽象方法
    * 具体交由它自己的子类来实现
    */ 
    @WorkerThread
    protected abstract void onHandleIntent(@Nullable Intent intent);
}

好了,具体的说明在源码中已经写得非常清楚了,因为这个IntentService的实现并不是那么的复杂,相信大家都能看懂,可能平时不太关注而已,最后要说的一点是因为它的里面封装了一个looper,所以我们的handler发送的消息都是通过looper顺序的取到,所以意味着IntentService是顺序的执行后台任务的,当有多个任务同时存在时,这些后台任务会按照我们代码发起的先后顺序排队执行的,好理解的哈?!

你可能感兴趣的:(android开发,技术,Android面试知识点系列)