IntentService的源码分析
出现原因,使用,优势
出现原因:
服务中的逻辑都是运行在主线程中的,如果我们想要执行耗时的操作,需要自己手动的开启线程,同时当任务执行结束后,需要手动的调用stopSelf或者stopService方法终止服务的运行。为了方便开发者进行开发,提供了IntentService。
使用
IntentService是一个抽象类,是Service的子类,使用IntentService只需要创建一个类继承IntentServive,然后重写其onHandleIntent方法即可。
优势
onHandleIntent方法是运行在子线程中的,我们可以在其中执行耗时的操作,当操作执行完毕后,IntentService会自动的结束运行。使用Intentservice免去了我们手动开启线程和关闭服务的过程,方便了开发。除了可以省去手动的创建线程,关闭服务的步骤之外,IntentService还有另一个优势,那就是由于IntentService是一个服务,所以IntentService的优先级比单纯的线程高,不容易被系统杀死,所以可以利用IntentService执行一些优先级比较高的后台任务。
源码分析
IntentService内部封装了HandlerThread和Handler,从onCrete方法可以看出:
1 | @Override |
onCreate方法中创建了HanlerThread同时获取创建的HandlerThread的内部的Looper,利用获取到的Looper创建了一个ServiceHandler对象。
每次启动IntentService的时候,他的onStartCommand方法就会被调用,在onStartCommand方法中调用了onStart方法,源码如下:
1 | @Override |
1 | @Override |
onStart方法中只是利用在onCreate方法中创建的ServiceHandler对象创建并且发送了消息,最终发送的消息会在ServiceHandler的handleMessage方法中被处理。
1 | private final class ServiceHandler extends Handler { |
ServiceHandler是IntentService的内部类,是Handler的子类,重写了其handleMessage方法,在handleMessage方法中调用了onHandleIntent方法处理消息,同时调用了stopSelf方法终止IntentService的运行。
onHandleIntent是IntentService的一个抽象方法,需要我们在子类中实现,onHandleIntent中接收到的参数Intent和启动IntentServie的时候startService(intent)的intent是相同的,我们可以从其中解析出启动Service的时候所传递进来的参数,从而对不同的任务作出去区分,对不同的任务进行不同的处理。
当onHandleIntent执行结束后,会执行stopSelf(int startId)来尝试停止服务,之所以使用stopSelf(int startId)方法而不是使用stopSelf方法来停止服务,是因为stopSelf方法会立即终止服务,而此时可能会有其他消息还没有被处理。stopSelf(int startId)方法会等所有的消息被处理了之后才终止服务的运行。如果当前只有一个后台任务,那么
stopSelf(int startId)会立即终止服务,如果由多个后台任务,会等所有的后台任务运行完后,终止服务。
从之前对Android的消息机制的分析我们可以知道,Handler的handleMessage方法最终会在Hanler所对应的Looper的loop方法中被调用,也就是说会在Looper所在的线程中被调用。由于创建ServiceHandler的时候传递进去的是HandlerThread的Looper,所以最终的handleMessage方法会在HandlerThread的run方法中被调用,这也就是为什么我们可以在onHandleIntent中执行耗时操作的原因。
此外还有一点需要注意,每次启动一个任务,都需要启动IntentService,而IntentService内部是通过消息的形式的请求任务的执行的,而Handler的Looper是顺序的处理任务的,所以IntentService也是顺序的处理任务的。
最后还有一个setIntentRedelivery方法需要讲解:
1 | public void setIntentRedelivery(boolean enabled) { |
mRedelivery的值将影响onStartCommand的返回结果,如果mRedelivery设置为true,那么onStartCommand将返回START_REDELIVER_INTENT;如果为false,将返回START_NOT_STICKY。
onStartCommand返回的结果将影响IntentService异常终止情况下重启服务时的行为,默认情况下,当IntentService因为系统内存吃紧或者其他原因被异常终止时,系统不会尝试重新启动服务,这时,如果IntentService#onStartCommand方法返回。
START_NOT_STICKY:服务不会重新创建,除非你再次调用startService
START_REDELIVER_INTENT:服务重新创建并启动,依次回调onCreate,onStartCommand,并且会把最后一次传给此服务的intent重新发给onStartCommand,也就是说如果有大量的intent投递了,那么只保证最近的intent会被重投递。。
由此我们可以发现,当我们的操作不是十分重要的时候,我们可以选择START_NOT_STICKY,这也是IntentService的默认选项,当我们认为操作十分重要时,则应该选择START_REDELIVER_INTENT 型服务。
建议阅读:Service#onStartCommand返回值解析
Service类onStartCommand()返回值讲解.
使用示例
1 | public class MyService extends IntentService { |