在Service启动流程(startService)的最后,分析了在调用startService
时可能存在的三种情况,本文分析第一种情况—Service已经启动。
Service启动流程(startService)中已经说明了Service已经启动时会执行函数sendServiceArgsLocked(r, false)
,接下来我们会分段分析这个函数。
private final void sendServiceArgsLocked(ServiceRecord r,
boolean oomAdjusted) {
final int N = r.pendingStarts.size();
if (N == 0) {
return;
}
理解这部分你的关键是r.pendingStarts
,系统会将对Service的所有startService
调用且还未执行保存在pendingStarts
的ArrayList数据结构中,如果r.pendingStarts.size()==0
,则表示对于Service来说,所有对于它的startService
调用都已经执行完,则不需要继续执行后面的逻辑。
while (r.pendingStarts.size() > 0) {
try {
ServiceRecord.StartItem si = r.pendingStarts.remove(0);
if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
+ r + " " + r.intent + " args=" + si.intent);
if (si.intent == null && N > 1) {
// If somehow we got a dummy null intent in the middle,
// then skip it. DO NOT skip a null intent when it is
// the only one in the list -- this is to support the
// onStartCommand(null) case.
continue;
}
这部分还是需要好理解的,ServiceRecord.StartItem
实例表示一次startService
调用。首先从`r.pendingStarts
中取出第一个,然后判断如果其intent是否为null,如果为null则表示此startService
不必执行。
si.deliveredTime = SystemClock.uptimeMillis();
r.deliveredStarts.add(si);
si.deliveryCount++;
.....
int flags = 0;
if (si.deliveryCount > 1) {
flags |= Service.START_FLAG_RETRY;
}
if (si.doneExecutingCount > 0) {
flags |= Service.START_FLAG_REDELIVERY;
}
r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
这部分的代码我们看到了一个r.deliveredStarts
结构,前面说过,r.pendingStarts
保存的是还未真正执行的startService
调用,r.deliveredStarts
记录的是已经真正执行过的startService调用
。接下来会有一个Binder的跨进程调用,直接进入ActivityThread即可看到scheduleServiceArgs
函数。
public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,
int flags ,Intent args) {
ServiceArgsData s = new ServiceArgsData();
s.token = token;
s.taskRemoved = taskRemoved;
s.startId = startId;
s.flags = flags;
s.args = args;
queueOrSendMessage(H.SERVICE_ARGS, s);
}
如果看了我前面几篇Activity启动过程的话,这样的函数应该不陌生了,这个函数最终会调用一下逻辑:
private void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
synchronized (this) {
if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
+ ": " + arg1 + " / " + obj);
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
mH.sendMessage(msg);
}
}
我们就直接到mH
的handleMessage
函数
case SERVICE_ARGS:
handleServiceArgs((ServiceArgsData)msg.obj);
ok,接着往下,感觉马上就到重点了,哈哈
private void handleServiceArgs(ServiceArgsData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
if (data.args != null) {
data.args.setExtrasClassLoader(s.getClassLoader());
}
int res;
if (!data.taskRemoved) {
res = s.onStartCommand(data.args, data.flags, data.startId);
} else {
s.onTaskRemoved(data.args);
res = Service.START_TASK_REMOVED_COMPLETE;
}
QueuedWork.waitToFinish();
try {
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, 1, data.startId, res);
} catch (RemoteException e) {
// nothing to do.
}
ensureJitEnabled();
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
throw new RuntimeException(
"Unable to start service " + s
+ " with " + data.args + ": " + e.toString(), e);
}
}
}
}
是不是看到onStartCommand
的踪影了,是的,到这就执行完onStartCommand
,这里还有一个非常重要的函数调用serviceDoneExecuting
,我们都知道onStartCommand
函数执行完后会返回一个标志,这个标志决定了Service的重启行为,但是系统究竟如何管理Service的重启行为呢,这个函数在后面会新开一篇分析。