转载请注明链接: https://blog.youkuaiyun.com/feather_wch/article/details/50300853
详解Service的原理有帮助,请点个赞!
Service原理详解
版本:2018/9/1-1(18:00)
基础(6)
1、Service是什么?
- 一种
服务型组件,用于在后台执行一系列计算任务(处理网络事务、播放音乐、文件读写、或者与ContentProvider交互)。- 没有界面的组件。
- Service具有两种状态:
启动状态和绑定状态- 本地Service运行在主线程(UI线程)中,因此不能进行耗时操作,需要创建子线程才可以。(BoradcastReceiver也是如此)
2、Service的两种状态
- 启动状态: 进行后台任务,
Service本身运行在主线程,因此耗时操作需要在新线程中处理- 绑定状态: 内部同样可以进行后台运算,但是此时
外界可以很方便与Service通信
3、Service如何停止?
- 如果是
启动状态:stopService()或者Service的stopSelf()来停止。- 如果是
绑定状态: unBindService()后,Service停止- 如果是
启动&绑定状态:需要执行unBindeService()和stopService()或者Service的stopSelf(),才能真正停止。
4、Service的分类
- 本地服务:一般的Service
- 远程服务: 通过
android:process属性,运行在独立进程中。
5、本地服务是什么?
- 该类服务依赖在主进程上而不是独立的进程,一定程度上节约资源。
- 本地服务因为在同一进程内,不需要IPC和AIDL进行交互。
bindService也方便很多。- 缺点:限制性大,
主进程被杀死后,服务便会终止。- 应用场景:需要依附某个进程的服务,比如音乐播放。
6、远程服务是什么?
- 该服务是
独立的进程,进程名为所在包名 + android:process指定的字符串。- 定义方式:用
android:process=".service"- 特点: 主进程被杀死后,该服务依然存在,不受其他进城影响,能为多个进程提供服务,具有灵活性。
- 会消耗更多资源,并且使用AIDL进行IPC比较麻烦,一般用于系统Service。
- 从Android 5.0开始,APP结束后会关闭相关进程树,因此相关的服务也会被杀死。
生命周期(4)
1、Service的生命周期

- 仅仅是
startService:onCreate()->onStartCommand()->onDestory()- 仅仅是
bindService:onCreate()->onBind()->onUnbind()->onDestory()- 同时使用
startService开启服务与bindService绑定服务:onCreate()->onStartCommand()->onBind()->onUnbind()->onDestory()
2、Service生命周期的
| 生命周期 | 解释 | 注意点 |
|---|---|---|
| onCreate() | 第一次启动时调用 | 适合只执行一次的操作 |
| onStartCommand() | 执行startService会调用 | 可能会多次调用,bindService不会调用 |
| onBind() | 执行bindSevice时调用 | 多次bindService不会导致调用多次 |
| onUnbind() | 执行unBindService()时调用 | 返回值会决定,再次bindService()会执行onBind()还是onRebind() |
| onDestory() | 销毁 | 做一些清理工作 |
3、onStartCommand()的返回值有什么用?
- 返回
START_STICKY时,如果Service因为内存不足,被系统杀掉后。如果有了多余内存,会尝试重新创建这个Service。- 并且会调用
onStartCommand(),其中的Intent将会为null。为了那些循环的音乐播放器,天气预报之类的服务。
// Service.java
public @StartResult int onStartCommand(Intent intent, @StartArgFlags int flags, int startId) {
onStart(intent, startId);
return mStartCompatibility ? START_STICKY_COMPATIBILITY : START_STICKY;
}
4、Service的unbindService生命周期

- 客户端执行
unBindService()后,回调onUnBind()方法,如果返回true,Service销毁。- onUnBind()如果返回false,判断是否调用了
stopSelf或者stopService,调用则继续消息Service- 没有调用,则不会销毁。客户端再次调用
bindService(), 会执行onRebind()- 销毁后,调用
bindService()会执行onBind()进行绑定。
通信(4)
1、Activity与Service间的通信方式
- Activity调用Service的方法:Activity通过调用bindService,在ServiceConnection的onServiceConnected可以获取到Service的对象实例,然后就可以访问
Service中的方法.- Service去主动通知Activity的方法:可以通过
回调来实现—在Activity的ServicConnection的onServiceConnected中去给Service设置实现的接口,该接口会在Service中被调用。- 通过
广播- 通过
EventBus
2、onBind()和onServiceConnected()实现通信
1-自定义Service,onBind()返回自定义的Binder
class MyService extends Service {
public IBinder onBind(Intent intent) {
return new MyBinder();
}
class MyBinder extends Binder{
MyService getService() {
return MyService.this;
}
}
public void method(){}
}
2-onServiceConnected()去接收Service
class MyServiceConnection implements ServiceConnection {
public void onServiceConnected(ComponentName name, IBinder service) {
// 1、获取Sevice
MyService myService = ((MyService.MyBinder)service).getService();
// 2、调用其方法
myService.method();
}
public void onServiceDisconnected(ComponentName name) {
}
}
3、ServiceConnection的onServiceDisconnected什么时候会被调用?
- 和Service连接意外中断。
- 如因为内存不足,Service被意外释放掉。
4、用户解绑和终止Service会调用onServiceDisconnected吗?
不会
启动模式(21)
1、Service的启动方式有什么区别
startService:Service与组件的生命周期无关,即使组件退出,Service依然存在。耗电,占内存。bindService:调用者退出后,Service也会退出。
2、startService
- Service无论调用多少次
startService,onCreate只会调用一次,onStartCommand会调用相应次数。- Service无论调用多少次
startService,只存在一个Service实例- 结束Service只需要调用一次
stopService或者stopSelf- Activity的退出并不会导致Service的退出—除非在onDestory里面调用stopService,但是
退出APP会导致Service的退出!- 系统资源不足的时候,服务可能会被
Kill
3、bindService
- Service通过
bindService启动,无论调用多少次,onCreate只会调用一次,且onStartCommand不会被调用。- 如果调用
Service的组件退出,如Activity,Service就会被停止。bindService开启的Service的通信比较方便,本地服务不需要AIDL和IPC,但是远程服务是需要AIDL和IPC的。
4、startService且同时bindService
onCreate之调用一次。startService调用几次,onStartCommand会调用相同次数。bindService不会调用onStartCommand- 调用
unBindService不会停止Service,必须调用stopService和Service自身的stopSelf来停止。- 如果想停止这种Service,
unBindeService和stopService都需要调用,缺一不可。
5、同时开启和绑定有什么作用?
- 能让
Service一直处于后台运行的状态,即使组件已经退出。- 同时通过
bindService能方便地与Service通信- 相比于
广播的方式,性能更高。
6、Service的注意点
- 手机发生旋转时,Activity的重新创建,会导致之前
bindService建立的连接断开,Service会因为COntext的销毁而自动停止。
startService流程
7、Service的启动方法
Intent intent = new Intent(this, MyService.class);
startService(intent);
- Service有
启动状态和绑定状态两个状态可以共存,Service可以既处于启动状态又处于绑定状态
8、Service的startService过程流程图和要点?
graph TD;
1(1.startService);
2(2.mBase.startService);
3(3.startServiceCommon);
4(4.ActivityManager.getService.startService);
5(5.mServices.startServiceLocked);
6(6.bringUpServiceLocked);
7(7.realStartServiceLocked);
8(8.app.thread.scheduleCreateService);
9(9.sendServiceArgsLocked);
10(10.handleMessage);
11(11.handleCreateService);
16(16.app.thread.scheduleServiceArgs);
17(17.handleMessage);
18(18.handleServiceArgs);
19(19.onStartCommand);
1-->2;
2-->3;
3-->4;
4-->5;
5-->6;
6-->7;
7-->8;
7-->9;
8-->10;
10-->11;
9-->16;
16-->17;
17-->18;
18-->19;
- startService(
ContextWrapper.java):Activity层层继承自ContextWrapper;内部交由ContextImpl的startService();典型的桥接模式- mBase.startService(
ContextImpl.java): 交给ContextImpl执行。- startServiceCommon(
ContextImpl.java): 通过ActivityManagerService启动服务;IPC- startService(
ActivityManagerService.java):通过ActiveServices进行后续工作—调用mServices.startServiceLocked。- startServiceLocked(
ActiveServices.java): bringUpServiceLocked- bringUpServiceLocked(
ActiveServices.java): realStartServiceLocked- realStartServiceLocked(
ActiveServices.java): 1、app.thread.scheduleCreateService 2、sendServiceArgsLocked- app.thread.scheduleCreateService(
ActivityThread.java):1. 创建Service 2. 发送消息CREATE_SERVICE给Handler H- sendServiceArgsLocked(): 用Service的其他方法(如onStartCommand)-IPC通信
- handleMessage(
ActivityThread.java): 处理消息- handleCreateService(
ActivityThread.java): 处理第12、13、14、15 四步的工作, 进行Service的创建工作- 16.app.thread.scheduleServiceArgs: IPC让ActivityThread只去执行其他的生命周期回调。发送消息给Handler H
- 17.handleMessage: 调用
handleServiceArgs- 18.handleServiceArgs: 执行其他的生命周期,如
onStartCommand- 19.onStartCommand: Service的回调方法
graph TD;
11(11.handleCreateService);
12(12.cl.loadClass);
13(13.makeApplication);
14(14.service.attach);
15(15.service.onCreate);
11-->12;
11-->13;
11-->14;
11-->15;
- handleCreateService(
ActivityThread.java): 处理第12、13、14、15 四步的工作- cl.loadClass().newInstance(): 类加载器创建Service实例。
- packageInfo.makeApplication: 用
LoadedApk创建Application实例- service.attach: 创建ContextImpl建立Context和Service的联系。
- service.onCreate(): Service的onCreate(), 并且将Service对象存储到ActivityThread中的一个列表中
9、ActiveServices是什么?
- 辅助ActivityManagerService进行Service管理
- 包括:启动、绑定、停止等
10、ServiceRecord是什么?
- 描述一个Service记录,贯穿整个启动过程
11、ContextWrapper是什么?
- ContextWrapper是Context实现类ContextImpl的包装类
- Activity、Service等都是直接或者间接继承自
ContextWrapper
12、ContextWrapper为什么是典型桥接模式?
见下面的
知识扩展部分
13、桥接模式和代理模式的区别?
见下面的
知识扩展部分
源码解析
14、Service的启动过程源码详细分析
/**
* ======================================
* 1. Activty层层继承自ContextWrapper
* 2. Activty的startService()方法来自于ContextWrapper
* 3. ContextWrapper最终由mBase(ContextImpl)完成-典型桥接
* ======================================
*/
//ContextWrapper.java
public ComponentName startService(Intent service) {
//1. mBase就是Context的实现ContextImpl对象(也就是Activity创建时关联的对象)
return mBase.startService(service);
}
//ContextImpl.java:直接调用startServiceCommon
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, false, mUser);
}
//ContextImpl.java
private ComponentName startServiceCommon(Intent service, boolean requireForeground, UserHandle user) {
......
//1. 让`ActivityManagerService`启动一个Service服务
ComponentName cn = ActivityManager.getService().startService(
mMainThread.getApplicationThread(), service, ...省略...);
......
}
//ActivityManagerService.java
public ComponentName startService(IApplicationThread caller, Intent service, ...) {
/**====================================
* 1. 通过mService(ActiveServices)完成后续过程
* 2. ActiveServices是辅助AMS进行Service管理的类
* -包括:启动、绑定、停止
* 3. `startServiceLocked`方法尾部会调用`startServiceInnerLocked`
*=====================================*/
res = mServices.startServiceLocked(caller, service, ...,userId);
}
//ActiveServices.java
ComponentName startServiceInnerLocked(...,ServiceRecord r) {
......
/**=========================================
* ServiceRecord描述的是一个Service记录(贯穿整个启动过程)
* 1. startServiceInnerLocked并没有完成具体启动工作,而是把后续任务交给了bringUpServiceLocked
* 2. bringUpServiceLocked内部调用`realStartServiceLocked`
* 3. realStartServiceLocked真正启动了Service
*==========================================*/
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
......
return r.name;
}
//ActiveServices.java
private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) {
......
/**========================================================
* 创建了Service对象,并且调用了onCreate()方法-IPC通信
* 1. app.thread对象是IApplicationThread类型(Binder)
* 2. 具体实现是ActivityThread(继承了ApplicationThreadNative)
*========================================================*/
app.thread.scheduleCreateService(r, r.serviceInfo, ......);
......
//2. 用于调用Service的其他方法(如onStartCommand)-IPC通信
sendServiceArgsLocked(r, execInFg, true);
......
}
//ActivityThread.java的内部类:ApplicationThread
public final void scheduleCreateService(IBinder token, ...,int processState) {
updateProcessState(processState, false);
CreateServiceData s = new CreateServiceData();
s.token = token;
s.info = info;
s.compatInfo = compatInfo;
/**========================================
* 1. 发送消息给Handler H处理
* 2. H会接受消息,并且调用ActivityThread的handleCreateService
*========================================*/
sendMessage(H.CREATE_SERVICE, s);
}
/**====================================
* 完成Service最终启动工作
* //ActivityThread.java
*=====================================*/
private void handleCreateService(CreateServiceData data) {
//1. 通过类加载器创建Service实例
Service service = null;
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = (Service) cl.loadClass(data.info.name).newInstance();
//2. 创建Application对象并调用其onCreate方法(Application是唯一的不会重复创建)
Application app = packageInfo.makeApplication(false, mInstrumentation);
//3. 创建ContextImpl对象并通过Service的attach方法建立两者关系(类似Activity的过程)
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
service.attach(context, this, data.info.name, data.token, app, ActivityManager.getService());
//4. 调用service的onCreate方法,并且将Service对象存储到ActivityThread中的一个列表中
service.onCreate();
mServices.put(data.token, service);
......
}
/**=============================================================
* ActivityThread中还会通过handleServiceArgs方法调用Service的onStartCommand
*=============================================================*/
private void handleServiceArgs(ServiceArgsData data) {
Service s = mServices.get(data.token);
......
//1. Service的onStartCommand方法
res = s.onStartCommand(data.args, data.flags, data.startId);
......
}
bindService流程
15、Service绑定流程图分析
graph TD;
1(ContextWrapper.bindService);
2(ContextImpl.bindServiceCommon);
Android Service深度解析:启动、绑定、生命周期与源码

本文详细介绍了Android Service的工作原理,包括Service的启动、绑定、生命周期和通信方式。重点解析了startService()和bindService()的流程,以及它们的区别和结合使用场景。同时,探讨了Service生命周期中的关键方法,如onCreate()、onStartCommand()、onBind()、onUnbind()和onDestroy()。此外,还讲解了Service的启动模式、ServiceConnection的onServiceConnected()、Service的桥接模式和组合模式。最后,文章提供了面试中常见的Service相关问题及其解答。
最低0.47元/天 解锁文章
820

被折叠的 条评论
为什么被折叠?



