图解Service的两种启动方式
众所周知,Service有两种启动方式
.
.
.
一.在新进程启动Service
在新进程启动Service共分为5个步骤:
step1:
App向AMS发送一个启动Service的消息,从AIDL视角看是这个样子的:
图中client代表了App端,APP通过AMN/AMP将要启动的service信息发送给了AMS。
Step2:
AMS检查Service是否在Manifest中声明了,没声明会直接报错。
AMS检查启动Service的进程是否存在,如果不存在,先把Service信息存下来,然后创建一个新的进程。
在AMS中,每个Service,都使用ServiceRecord对象来保存。
Step3:
新进程启动后,也会创建新的ActivityThread,然后把ActivityThread对象通过AMP传递给AMS,告诉AMS,新进程启动成功了。
Step4:
AMS把传进来的ActivityThread对象改造为ApplicationThreadProxy,也就是ATP,通过ATP,把要启动的Service信息发送给新进程。
Step5:
新进程通过ApplicationThread接收到AMS的信息,和前面介绍的启动Activity的最后一步相同,借助于ActivityThread和H,执行Service的onCreate方法。在此期间,为Service创建了Context上下文对象,并与Service相关联。
这里的H与Activity启动过程中的H是同一个Handler类…到这里在新进程中启动service成功了
.
.
.
二.在当前进程中启动Service
相比上面的过程,在当前进程启动Service就简单多了:
1.App向AMS请求启动Service
2.AMS例行检查,比如Service是否声明了,把Service在AMS这边注册。AMS发现要启动的Service就是App所在的Service,就通知App启动这个Service。
3…Service启动成功
.
.
三.在当前进程绑定新启动的Service
Step1.APP向AMS请求绑定Service
Step2.AMS例行检查,比如Service是否声明了,把Service在AMS这边注册。AMS发现要启动的Service就是App所在的Service,就通知App对Service进行绑定。
Step3.App收到AMS的第一个消息,启动Service
Step4.App收到AMS第二条消息,绑定service,并将一个binder传给AMS
Step5.AMS收到binder后,将其发送给APP
Step6.APP收到binder对象,Service启动成功
Step1:
step5,6:
图片是自己画的,地址是:ProcessOn
四.IntentSerivice与Service的区别
首先我们清楚,Service虽然叫做后台服务,但是Service中却并不可以做耗时操作,否则会出现ANR异常。
所以多数情况下我们只能不断的在service中开辟线程,利用新的新线程去做 耗时操作。但这样做的缺点就是服务会在后台一直运行,想要停止只能手动调用stopService()方法,或者stopself()方法。于是Android给我们提供了IntentService。
IntentService的特点:
- IntentService内部有一个工作线程,专门用来处理耗时操作,所以我们不需要在IntentService中去开辟线程。
- IntentService当任务完成后,会自己停止。
- IntentService 维护了一个工作队列。所以我们可以多次启动IntentService ,它会将每个耗时操作存放在工作队列中,然后再IntentService 的 onHandleIntent 回调方法中执行,每次只会有一个工作线程去处理耗时操作,执行完之后再执行下一个
- IntentService的启动方式与普通Service相同
本文参考:
https://www.jianshu.com/p/058d35e01dd1