IntentService源码分析

概述:

IntentService是Service的子类,起Service的时候如果需要处理耗时任务往往需要启动一个Thread,因为Service是运行在主线程里的。IntentService内部有一个HandlerThread,在IntentService的Oncreate方法中就启动了这个HandlerThread。所以IntentService就是一个有子线程有消息循环有handler的Service,并且IntentService在处理完所有任务之后会自己结束自己(调用stopSelf)。

IntentService缺点,无法等待,Service处理完事情就自动关闭,不适合处理长期任务,比如监听socket,此种场景用Service更合适。

有个场景特别适用,当activity要退出的时候,我们又想保存某些数据,而保存数据比较耗时,此时可以用IntentService来做。也可以在activity启动一个子线程,由子线程来做,但是子线程不是四大组件,容易被杀死

问题1:IntentService跟Handler怎么关联上的?

IntentService内部有个ServiceHandler
    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);
        }
    }

每调用一次startService会调用IntentService的onStartCommand()方法,内部调用onStart()方法

    public void onStart(Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }

onStart()内部根据intent与startId构建一个Message,然后使用ServiceHandler发出去,交给Handler处理,内部的Looper负责从消息队列中取消息,然后交给ServiceHandler处理.

这时我们发现一件事情,每个消息,Handler处理完了都会调用一次stopSelf(msg.arg1);

哎,这不是直接结束Intentservice了吗?难道处理完一次消息就会关掉Service吗?

当然不是的,请看问题2

问题2:IntentService是如何结束自己的?他怎么保证所有任务都结束了?

我们来看 stopSelf(int startId)有个int参数,这个参数是哪里来的呢?什么用?

我们来看onStart

public void onStart(Intent intent, int startId)

Service可以被start任意次。所以需要一个startId来标识当前Service被启动了多少次,比如调了2次startService,每一次startService都会调onStart,那么第一次onStart的startId就是1,第二次onStart的startId就是2.

再看stopSelf(int startId),如果当前Service的startId和stopSelf里的一致,那就停止Service,否则不做任何事情。


来看一个场景,一个Service在处理完某件事情之后,想关闭Service,可是Service可能在处理别的事情。

比如调了2次startService,处理2件事情,第一件事情处理完了,Service想要关闭,但是此时如果Service还在处理第二件事情呢?所以不能直接关闭,于是stopService就有了int参数叫startId。第一次startService时,startId为1,第二次startService时,startId为2,如果stopService(1)就无法关闭Service,stopService(2)就可以关闭Service。
IntentService中stopSelf(msg.arg1);,arg1就是当前startService对应的startId,除非这个startId是此Service的当前启动次数,否则不会关闭。因此就保证了IntenService会在处理完所有的任务之后自动关闭。

stopSelf()和stopSelf(int startId)区别

    public final void stopSelf() {
        stopSelf(-1);
    }

startSelf(int startId)会检查startId与当前Service的startId是否一致,一致就stop,不一致就不做任何事

代码com.android.server.am.ActiveServices#stopServiceTokenLocked

<span style="font-size:14px;">   if (r.getLastStartId() != startId) {
                    return false;
                }</span>


stopSelf()就不检查,会直接stop。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值