1. 程式人生 > >Android Activity啟動流程分析

Android Activity啟動流程分析

概述

Activity作為Android的四大元件之一,Android主要的介面組成部分,用於直接跟使用者進行互動操作,在面試中與Activity相關的知識也是經常被問到,如果你面試的高階崗位,那麼對Activity的啟動和繪製流程就必須的熟悉,本文將從Activity的啟動流程來分析Activity。啟動Activity的方式大致有兩種:一種是在桌面點選應用程式的圖示,進入應用程式的主介面;另一種是在應用程式中,進入一個新的Activity。前者屬於launcher啟動的範疇,本文不做具體的深入分析,後面會具體的分析,不過它的實質是從一個應用的Activity進入另一個應用Activity。
因此,不管是從桌面進入應用主介面,還是在應用裡進入一個新的Activity,最終都會呼叫Activity$startActivity方法。


值得注意的是,Android 5.0,7.0等版本中啟動Activity的流程略微有一些細小的改變,但這並不妨礙我們理解Activity的啟動流程。

Binder機制

首先,我們要介紹下Android系統中一個重要的內容:Binder機制。為了滿足程序間的通訊,Android系統將程序分為了使用者(Zygote)程序和系統(SystemServer)程序以及各種應用程序等,為了能夠實現各種程序之間的通訊,Android系統採用了自己的程序間通訊方式Binder機制。其中主要涉及到了四種角色:Binder Client,Binder Server,Binder Manager, Binder driver。各種角色之間的關係可以參考下面這張圖的介紹:
這裡寫圖片描述

啟動Activity流程解讀

當我們使用startActivity() 啟動另一個Activity後,主要會呼叫以下的一些函式。

MyActivity.startActivity() 
Activity.startActivity() 
Activity.startActivityForResult 
Instrumentation.execStartActivty 
ActivityManagerNative.getDefault().startActivityAsUser() 

首先,我們來看一下startActivity()函式的原始碼:

@Override
    public
void startActivity(Intent intent) { this.startActivity(intent, null); } @Override public void startActivity(Intent intent, @Nullable Bundle options) { if (options != null) { startActivityForResult(intent, -1, options); } else { startActivityForResult(intent, -1); } }

其實,startActivity還有幾個其他過載的方法,但是最終都會執行到Activity$startActivityForResult方法。如果是呼叫startActivity(intent)啟動Activity,那麼requestCode引數則傳入-1,表示需要返回Activity的資料。

到此繼續往下看,startActivityForResult方法的具體實現如下:

    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) {
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            if (requestCode >= 0) {
                // If this start is requesting a result, we can avoid making
                // the activity visible until the result is received.  Setting
                // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
                // activity hidden during this time, to avoid flickering.
                // This can only be done when a result is requested because
                // that guarantees we will get information back when the
                // activity is finished, no matter what happens to it.
                mStartedActivity = true;
            }

            cancelInputsAndStartExitTransition(options);
            // TODO Consider clearing/flushing other event sources and events for child windows.
        } else {
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                // Note we want to go through this method for compatibility with
                // existing applications that may have overridden it.
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }

在上面的程式碼中,mParent進行了一個判Null操作,可以發現由於我們是第一次啟動Activity,所以這裡的mParent為空,所以會執行if分之,然後呼叫mInstrumentation.execStartActivity方法,並且這裡需要注意的是,有一個判斷邏輯。即:

if (requestCode >= 0) {
    mStartedActivity = true;
}

前面說過,呼叫startActivityForResult的時候只有requestCode的值大於等於0,onActivityResult才會被回撥。

Instrumentation

然後我們看一下mInstrumentation.execStartActivity方法的具體實現。在看execStartActivity方法之前,首先看一下Instrumentation,Instrumentation是android系統中啟動Activity的一個實際操作類,也就是說Activity在應用程序端的啟動實際上就是Instrumentation執行的。那為什麼是這樣呢?實際上acitivty的啟動分為應用程序端的啟動和SystemServer服務程序端的啟動的,多個應用程序相互配合最終完成了Activity在系統中的啟動的,而在應用程序端的啟動實際的操作類就是Intrumentation來執行的。

為了方便理解,我們直接看execStartActivity函式原始碼:

 public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        Uri referrer = target != null ? target.onProvideReferrer() : null;
        if (referrer != null) {
            intent.putExtra(Intent.EXTRA_REFERRER, referrer);
        }
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    ActivityResult result = null;
                    if (am.ignoreMatchingSpecificIntents()) {
                        result = am.onStartActivity(intent);
                    }
                    if (result != null) {
                        am.mHits++;
                        return result;
                    } else if (am.match(who, null, intent)) {
                        am.mHits++;
                        if (am.isBlocking()) {
                            return requestCode >= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

如上,execStartActivity主要有以下幾個引數:
this,為啟動Activity的物件;
contextThread,為Binder物件,是主程序的context物件;
token,也是一個Binder物件,指向了服務端一個ActivityRecord物件;
target,為啟動的Activity;
intent,啟動的Intent物件;
requestCode,請求碼;
options,引數;
通過,execStartActivity方法可以發現,該方法主要呼叫ActivityManager.getService()方法,繼續檢視ActivityManager$getService原始碼。

/**  
 * @hide  
 */  
public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    } 

//繼續檢視  

private static final Singleton<IActivityManager> IActivityManagerSingleton =  
        new Singleton<IActivityManager>() {  
            @Override  
            protected IActivityManager create() {  
                final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);  
                final IActivityManager am = IActivityManager.Stub.asInterface(b);  
                return am;  
            }  
        };  

 //...code  

}

可以發現,IActivityManager.Stub.asInterface(b),那麼繼續看asInterface方法的實現:

static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }

        return new ActivityManagerProxy(obj);
    }

asInterface()返回一個ActivityManagerProxy物件,ActivityManagerProxy繼承與IActivityManager,到了這裡就引出了我們android系統中很重要的一個概念:Binder機制。

IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE)

如上,是獲取一個關聯了系統服務ActivityManagerService的Binder物件。所以,IBinder最終和ActivityManagerService形成了繫結關係。

public class ActivityManagerService extends IActivityManager.Stub  
       implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {  


   }  

所以,ActivityManager.getService().startActivity(…)的最終呼叫的是ActivityManagerService的startActivity方法。

ActivityManagerService啟動Activity

首先來看一下,ActivityManagerService$startActivity的相關原始碼。

@Override  
public final int startActivity(IApplicationThread caller, String callingPackage,  
        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,  
        int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {  
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,  
            resultWho, requestCode, startFlags, profilerInfo, bOptions,  
            UserHandle.getCallingUserId());  
}  

ActivityManagerService啟動Activity主要會涉及到以下的一些方法。

ActivityManagerService.startActivity() 
ActvityiManagerService.startActivityAsUser() 
ActivityStackSupervisor.startActivityMayWait() 
ActivityStackSupervisor.startActivityLocked() 
ActivityStackSupervisor.startActivityUncheckedLocked() 
ActivityStackSupervisor.startActivityLocked() 
ActivityStackSupervisor.resumeTopActivitiesLocked() 
ActivityStackSupervisor.resumeTopActivityInnerLocked() 

當ActivityManagerService呼叫startActivity方法後,該方法呼叫的是startActivityAsUser(),該方法的原始碼如下:

@Override  
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,  
        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,  
        int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {  
    enforceNotIsolatedCaller("startActivity");  
    userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),  
            userId, false, ALLOW_FULL_ONLY, "startActivity", null);  
    // TODO: Switch to user app stacks here.  
    return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,  
            resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,  
            profilerInfo, null, null, bOptions, false, userId, null, null,  
            "startActivityAsUser");  
}  

可以看到這裡只是進行了一些關於userid的邏輯判斷,然後就呼叫mStackSupervisor.startActivityMayWait方法,該方法涉及的原始碼比較多,下面擷取一些核心的程式碼實現:

final int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,
            Bundle options, boolean ignoreTargetSecurity, int userId,
            IActivityContainer iContainer, TaskRecord inTask) {
            ...

            int res = startActivityLocked(caller, intent, resolvedType, aInfo,
                    voiceSession, voiceInteractor, resultTo, resultWho,
                    requestCode, callingPid, callingUid, callingPackage,
                    realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
                    componentSpecified, null, container, inTask);
            ...
            return res;
    }

該方法在啟動Activity後執行了一些邏輯判斷後,最終呼叫startActivityLocked方法。

final int startActivityLocked(IApplicationThread caller,
            Intent intent, String resolvedType, ActivityInfo aInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode,
            int callingPid, int callingUid, String callingPackage,
            int realCallingPid, int realCallingUid, int startFlags, Bundle options,
            boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
            ActivityContainer container, TaskRecord inTask) {
        int err = ActivityManager.START_SUCCESS;

        ...
        err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
                startFlags, true, options, inTask);

        ...
        return err;
    }

這個方法中主要構造了ActivityManagerService端的Activity物件–>ActivityRecord,並在執行了一些邏輯判斷後呼叫了startActivityUncheckedLocked方法。

final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
            boolean doResume, Bundle options, TaskRecord inTask) {
        ...
        ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
        targetStack.mLastPausedActivity = null;
        targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
        if (!launchTaskBehind) {
            // Don't set focus on an activity that's going to the back.
            mService.setFocusedActivityLocked(r, "startedActivity");
        }
        return ActivityManager.START_SUCCESS;
    }

startActivityUncheckedLocked方法中只要執行了不同啟動模式不同棧的處理,並最後呼叫了startActivityLocked的過載方法。

final void startActivityLocked(ActivityRecord r, boolean newTask,
            boolean doResume, boolean keepCurTransition, Bundle options) {
        ...
        if (doResume) {
            mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
        }
    }

而這個startActivityLocked方法主要執行初始化了windowManager服務,然後呼叫resumeTopActivitiesLocked方法。

boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
            Bundle targetOptions) {
        if (targetStack == null) {
            targetStack = mFocusedStack;
        }
        // Do targetStack first.
        boolean result = false;
        if (isFrontStack(targetStack)) {
            result = targetStack.resumeTopActivityLocked(target, targetOptions);
        }

        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityStack stack = stacks.get(stackNdx);
                if (stack == targetStack) {
                    // Already started above.
                    continue;
                }
                if (isFrontStack(stack)) {
                    stack.resumeTopActivityLocked(null);
                }
            }
        }
        return result;
    }

該函式最終又呼叫了resumeTopActivityLocked方法,

final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
        if (mStackSupervisor.inResumeTopActivity) {
            // Don't even start recursing.
            return false;
        }

        boolean result = false;
        try {
            // Protect against recursion.
            mStackSupervisor.inResumeTopActivity = true;
            if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {
                mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;
                mService.updateSleepIfNeededLocked();
            }
            result = resumeTopActivityInnerLocked(prev, options);
        } finally {
            mStackSupervisor.inResumeTopActivity = false;
        }
        return result;
    }

ApplicationThread

前面說過,ApplicationThread是ActivityThread的內部類,因此ApplicationThread可以呼叫外部類ActivityThread的方法,啟動Activity的操作交給了ActivityThread來處理。那麼首先來看一下ApplicationThread$scheduleLaunchActivity的原始碼實現。

@Override  
       public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,  
               ActivityInfo info, Configuration curConfig, Configuration overrideConfig,  
               CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,  
               int procState, Bundle state, PersistableBundle persistentState,  
               List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,  
               boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {  

           updateProcessState(procState, false);  

           ActivityClientRecord r = new ActivityClientRecord();  

           r.token = token;  
           r.ident = ident;  
           r.intent = intent;  
           r.referrer = referrer;  
           r.voiceInteractor = voiceInteractor;  
           r.activityInfo = info;  
           r.compatInfo = compatInfo;  
           r.state = state;  
           r.persistentState = persistentState;  

           r.pendingResults = pendingResults;  
           r.pendingIntents = pendingNewIntents;  

           r.startsNotResumed = notResumed;  
           r.isForward = isForward;  

           r.profilerInfo = profilerInfo;  

           r.overrideConfig = overrideConfig;  
           updatePendingConfiguration(curConfig);  

           sendMessage(H.LAUNCH_ACTIVITY, r);  
       }  

上面程式碼最終呼叫了ActivityThread$sendMessage函式,該部分程式碼如下:

private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {  
        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;  
        if (async) {  
            msg.setAsynchronous(true);  
        }  
        mH.sendMessage(msg);  
} 

上面使用了Handler機制,來看一下H$handleMessage原始碼。

private class H extends Handler {  

    //...code  
    public void handleMessage(Message msg) {  
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));  
            switch (msg.what) {  
                case LAUNCH_ACTIVITY: {  
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");  
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;  
                    r.packageInfo = getPackageInfoNoCheck(  
                            r.activityInfo.applicationInfo, r.compatInfo);  
                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");  
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);  
                } break;  

    //...code  

}  

當接受到訊息後,最終呼叫ActivityThread$handleLaunchActivity方法啟動Activity。

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {  
    //...  

    Activity a = performLaunchActivity(r, customIntent);  

    //...  

    if (a != null) {  
        //...  

        handleResumeActivity(r.token, false, r.isForward,  
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);  

        //...  

    } else {  
        // If there was an error, for any reason, tell the activity manager to stop us.  
        try {  
             ActivityManager.getService()  
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null,  
                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);  
            } catch (RemoteException ex) {  
                throw ex.rethrowFromSystemServer();  
            }  
    }  

}  

也就是performLaunchActivity,到此我相信大部分的同學都可以看得懂了