Service stopSelf(int statId)和onStartcommand(Intent intent,int flags,int startId)

时间:2023-03-09 19:34:27
Service stopSelf(int statId)和onStartcommand(Intent intent,int flags,int startId)

Stopping a service

A started service must manage its own lifecycle. That is, the system does not stop or destroy the service unless it must recover system memory and the service continues to run after onStartCommand() returns. So, the service must stop itself by calling stopSelf() or another component can stop it by calling stopService().

Once requested to stop with stopSelf() or stopService(), the system destroys the service as soon as possible.

However, if your service handles multiple requests to onStartCommand() concurrently, then you shouldn't stop the service when you're done processing a start request, because you might have since received a new start request (stopping at the end of the first request would terminate the second one). To avoid this problem, you can usestopSelf(int) to ensure that your request to stop the service is always based on the most recent start request. That is, when you call stopSelf(int), you pass the ID of the start request (the startId delivered toonStartCommand()) to which your stop request corresponds. Then if the service received a new start request before you were able to call stopSelf(int), then the ID will not match and the service will not stop.

上面是来自google官网的Service说明文档,大致意思是说:其一,用户必须自己管理Service的生命周期,其二,调用stopSelf(int)方法时,传入的startId和onStartcommand方法被回调时的startId应该相对应,这样就可以确保,当Service同时处理多个请求时,就不会因为第一个请求的结束后立即停止Service导致第二个请求没有被完全执行。上文红色字体标出stopSelf(int)方法结束Service时,会以最近的请求的startId为标准,也就是说,系统在回调stopSelf(startId)时,会用传入的startId和最近的请求的startId相比较,如果相同,则退出Service,否则,Service不会被停止。

Service stopSelf(int statId)和onStartcommand(Intent intent,int flags,int startId)

如上图,水平方向上三个箭头,代表三个请求Service的任务,假设它们的执行时间都是一样的,进一步假设它们的startId分别为startId1、startId2和startId3。在T1时刻,Service接收到第一个请求,在T4时刻第一个请求已经被处理完毕,这时调用stopSelf(startId1),结束Service的生命周期时,发现最近请求的startId为startId3(T3时刻第三个请求到来了),所以T4时刻根本停不掉Service,同理T5时刻也停不调,直到T6时刻时,三个排队的任务都处理完了,才成功结束Service的生命周期。

所以综上,得到基本的结论:

  1. Service的stopSelf(int)方法被调用时不一定就能将自己的生命周期结束掉。
  2. onStartCommand方法由AMS通过消息回调,所以是顺序执行的,且在主线程中回调。
  3. AMS中保存一个ServiceRecord,其实它是一个binder token,可以跨进程传递代理对象到应用ActivityThread中,从而找到对应的Service对象。