startService啟動流程---Service已經啟動
在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的重啟行為呢,這個函式在後面會新開一篇分析。