1. 程式人生 > >startService啟動流程---Service已經啟動

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);
    }
}  

我們就直接到mHhandleMessage函式

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