本文基于 Android 7.1.1 源码分析,转载请说明出处!
0 综述
对于 Service,我们除了可以调用 stopService 来停止服务,服务自身也可以调用 stopSelf 方法停止,下面我们来看看这几个方法!1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26public final void stopSelf() {
stopSelf(-1);
}
public final void stopSelf(int startId) {
if (mActivityManager == null) {
return;
}
try {
mActivityManager.stopServiceToken(
new ComponentName(this, mClassName), mToken, startId);
} catch (RemoteException ex) {
}
}
public final boolean stopSelfResult(int startId) {
if (mActivityManager == null) {
return false;
}
try {
return mActivityManager.stopServiceToken(
new ComponentName(this, mClassName), mToken, startId);
} catch (RemoteException ex) {
}
return false;
}
这几个方法有什么区别呢?这里先简单的说一下:
stopSelf()方法,会调用第二个stopSelf(int startId)方法,如果服务之前通过startService方法启动过了,那该方法就等价于调用stopService方法!stopSelf(int startId)方法,是stopSelfResult方法的旧版本,不会返回任何结果!stopSelfResult(int startId)方法,通过指定启动项的startId来停止服务,该方法也等价于stopService方法,但是它能避免在停止服务时,服务仍没有接收到启动项!
下面,我们来看看该方法的调用过程!
1 系统进程
这里省略了 Binder 调用的过程,Binder 客户端发送 STOP_SERVICE_TOKEN_TRANSACTION 到 Binder 服务端,进入系统进程中!!
1.1 ActivityManagerS.stopServiceToken
1 | @Override |
这里我们来解释一下参数:
- ComponentName className:服务对应的
ComponentName对象。封装了组件信息,包括其所在的运行环境,对应的.class文件名! - IBinder token:
ServiceRecord对象,在启动服务时,会将该对象保存到Service的 - int startId:启动项的
id值;
1.2 ActiveServices.stopServiceToken
1 | boolean stopServiceTokenLocked(ComponentName className, IBinder token, |
如果没指定启动项的 id,即:startId >= 0,那就要判断下该 id 是否对应了最后一个启动项,如果是,才会立刻停止!!
如果指定了启动项的 id,即:startId < 0,那就立刻停止服务;
最后调用了 bringDownServiceIfNeededLocked 来停止服务,这里的逻辑就和 stopService 中的逻辑一样了!
下面我们来看看其他的几个方法:
- 获得对应的
ServiceRecord对象:1
2
3
4
5private final ServiceRecord findServiceLocked(ComponentName name,
IBinder token, int userId) {
ServiceRecord r = getServiceByName(name, userId);
return r == token ? r : null;
} - 找到
id对应的启动项StartItem:1
2
3
4
5
6
7
8
9
10
11
12public StartItem findDeliveredStart(int id, boolean remove) {
final int N = deliveredStarts.size();
for (int i=0; i<N; i++) {
StartItem si = deliveredStarts.get(i);
if (si.id == id) {
if (remove) deliveredStarts.remove(i);
return si;
}
}
return null;
}
这里就不在多书了,过程很清晰哦!