本文基于 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;
}
这里就不在多书了,过程很清晰哦!