深入剖析Service特性

来源:互联网 发布:怎么把淘宝店做起来 编辑:程序博客网 时间:2024/05/29 13:00


When a service is started, it gets created first, and its  onStartCommand method is called. 
Android has enough provisions to keep this  process in memory so that the service can 
serve multiple incomi ng client requests.  
There is a difference between a service process  being in memory and running. A service 
runs only in response to startService, which calls its onStartCommand method. Just 
because this method is not executing doesn’t mean the service process is not in 
memory. Sometimes, people refer to this service as running even though it is just sitting 
there and claiming some resour ces but not actually executing  anything. This is what it 
typically means when Android claims t hat it keeps the service running.  
In fact, if a startService call, resulting in an onStartCommand, takes more than five to ten 
seconds, this will result in ANR message and could kill the process hosting the service. 
Without a worker thread, a service cannot run for longer than ten seconds. So you 
should distinguish between a  service that’s availabl e and one that’s running. 
Android does its best to keep a service available in memory. However, under demanding 
memory conditions, Android may choose  to reclaim the process and call the 
onDestroy()  method of the service.  
NOTE:  Android tries to call the  onDestroy()  method for a service to reclaim its resources when 
the service is not executing its  onCreate(),  onStart() , or  onDestroy()  method. 

 
However, unlike an activity that is shut do wn, a service is scheduled to restart again 
when resources are available if there are pending  startService intents in the queue. The 
service will be woken up and the next intent delivered to it via onStartCommand(). Of 
course,  onCreate() will be called when the service is brought back.  
NOTE:  Because services are automatically restarted if  they are not explicitly stopped, it is 
reasonable to think that, unlike activities a nd other components, a service component is 
fundamentally a sticky component.
 


Details of a Nonsticky Service 

What is a nonsticky service then? 
Let’s talk about a situation when a service is not automatically restarted. After a client 
calls startService, the service is created and  OnStartCommand  is called to do its work. 
This service will not be automatically re started if a client explicitly calls stopService .  
This stopService  method depending on how many  clients are still connected, can move 
the service into a stopped state,  at which time the service’s  onDestroy  method is called 
and the service life cycle is complete. Once a service has been stopped like this by its 
last client, the service will not be brought back.  
This protocol works well when everything happens as per design, where start and stop 
methods are called and executed in sequence and without a miss. 
Prior to Android 2.0, devices have seen a lot of services hanging around and claiming 
resources even though there was no work to be done, meaning Android brought the 
services back into memory even though t here were no messages in the queue. This 
would have happened when stopService  was not invoked either because of an 
exception or because the process was taken out between onStartCommand and 
stopService . 
Android 2.0 introduced a solution so that  we can indicate to the system, if there are no 
pending intents, that it s houldn’t bother restarting the service. This is OK because 
whoever started the service to do the work will call it again, such as the alarm manager. 
This is done by returning the nonsticky flag (Service.START_NOT_STICKY) from 
onStartCommand.  
However, nonsticky is not really that nonstic ky. Remember, even if we mark the service 
as nonsticky, if there are pend ing intents, Android will bring  the service back to life. This 
setting applies only when there are no pending intents.  
Details of a Sticky Service 
What does it mean for a service to be really sticky then? 
The sticky flag (Service.START_STICKY) means that Android should restart the service 
even if there are no pending intents. When the service is restarted, call onCreate  and 
onStartCommand with a null intent. This will give the  service an opportunity, if need be, to 
call  stopSelf if that is appropriate. The implicatio n is that a service that is sticky needs 
to deal with null intents on restarts.  
A Variation of Nonsticky: Redeliver Intents 
Local services in particular follow a pattern where  onStart  and stopSelf are called in 
pairs. A client calls  onStart . The service, when it finishes that work, calls  stopSelf. You 
can see this clearly in the implementat ion of the  IntentService  utility class in Listing 19–
10. 
If a service takes, say, 30 minutes  to complete a task, it will not call stopSelf for 30 
minutes. Meanwhile, the service is reclaimed. If we use t he nonsticky flag, the service 
will not wake up, and we would never have called stopSelf.  
Many times, this is OK. However, if you want to make sure whether these two calls 
happen for sure, you can tell Android to not to unqueue  the  start  event until stopSelf is 
called. This ensures that, when the service is  reclaimed, there is  always a pending event 
unless the  stopSelf is called. This is called  redeliver  mode, and it can be indicated in 
reply to the  onStartCommand method by returning the  Service.START_REDELIVER  flag.  
Specifying Service Flags in OnStartCommand 
Interestingly, stickiness is tied to o nStartCommand , and not to  onCreate, for a service. 
This is a bit odd, because so far, we have b een talking about a serv ice being in sticky, 
nonsticky, or redeliver mode as if these were service-level attributes. However, this 
determination for the nature  of a service is made based on the return value from 
OnStartCommand. Wonder what the goal here is? B ecause for the same service instance, 
OnStartCommand is called many times, once for each  startService. What if the method 
returns different flags indicat ing different service behaviors ? Perhaps the best guess is 
that the last returned value is what  determines the service behavior.  
Picking Suitable Stickiness 
Given the combination of possible service behaviors, what type of service is suitable for 
a long-running broadcast receiver? We believe a simple, nonsticky service, which just 
assumes the service will stop if there are  no pending messages in the queue, will do. We 
are finding it hard to think that there is a use case  for sticky long-running broadcast 
receivers, especially if we want to use  IntentService , which expects the service to stop 
if there are no pending intents.  
You will see this conclusion in the implementation of our  long-running service 
abstraction in the upcoming Li sting 19–18, where we have re turned the nonsticky flag. 

原创粉丝点击