Android之Activity啟動流程詳解(基於api28)

一隻修仙的猿發表於2020-12-12

前言

Activity作為Android四大元件之一,他的啟動絕對沒有那麼簡單。這裡涉及到了系統服務程式,啟動過程細節很多,這裡我只展示主體流程。activity的啟動流程隨著版本的更替,程式碼細節一直在進行更改,每次都會有很大的修改,如android5.0 android8.0。我這裡的版本是基於android api28,也是目前我可以查得到的最新原始碼了。事實上大題的流程是相同的,掌握了一個版本,其他的版本通過原始碼也可以很快地掌握。

因為涉及到不同的程式之間的通訊:系統服務程式和本地程式,在最新版本的android使用的是AIDL來跨程式通訊。所以需要對AIDL有一定的瞭解,會幫助理解整個啟動流程。

原始碼部分的講解涉及到很多的程式碼講解,可能會有一點不適,但還是建議看完原始碼。原始碼的關鍵程式碼處我都會加上註釋,方便理解。

程式碼不會過分關注細節,只注重整體流程。想知道具體細節可以去檢視原始碼。每份程式碼所在的路徑我都會在程式碼前面標註出來,各位可以去檢視相對應的原始碼。

每部分原始碼前我都會放流程圖,一定要配合流程圖食用,不然可能會亂。

整體流程概述

這一部分側重於對整個啟動流程的概述,在心中有大體的概念,這樣可以幫助對下面具體細節流程的理解。

普通Activity的建立

普通Activity建立也就是平常我們在程式碼中採用startActivity(Intent intent)方法來建立Activity的方式。總體流程如下圖:

普通Activity啟動整體流程.png

啟動過程設計到兩個程式:本地程式和系統服務程式。本地程式也就是我們的應用所在程式,系統服務程式為所有應用共用的服務程式。整體思路是:

  1. activity向Instrumentation請求建立

  2. Instrumentation通過AMS在本地程式的IBinder介面,訪問AMS,這裡採用的跨程式技術是AIDL。

  3. 然後AMS程式一系列的工作,如判斷該activity是否存在,啟動模式是什麼,有沒有進行註冊等等。

  4. 通過ClientLifeCycleManager,利用本地程式在系統服務程式的IBinder介面直接訪問本地ActivityThread。

    ApplicationThread是ActivityThread的內部類,IApplicationThread是在遠端服務端的Binder介面

  5. ApplicationThread接收到服務端的事務後,把事務直接轉交給ActivityThread處理。

  6. ActivityThread通過Instrumentation利用類載入器進行建立例項,同時利用Instrumentation回撥activity的生命中週期

這裡涉及到了兩個程式,本地程式主要負責建立activity以及回撥生命週期,服務程式主要判斷該activity是否合法,是否需要建立activity棧等等。程式之間就涉及到了程式通訊:AIDL。(如果不熟悉可以先去了解一下,但可以簡單理解為介面回撥即可)

下面介紹幾個關鍵類:

  • Instrumentation是activity與外界聯絡的類(不是activity本身的統稱外界,相對activity而言),activity通過Instrumentation來請求建立,ActivityThread通過Instrumentation來建立activity和呼叫activity的生命週期。

  • ActivityThread,每個應用程式唯一一個例項,負責對Activity建立的管理,而ApplicationThread只是應用程式和服務端程式通訊的類而已,只負責通訊,把AMS的任務交給ActivityThread。

  • AMS,全稱ActivityManagerService,負責統籌服務端對activity建立的流程。

    其他的類,後面的原始碼解析會詳解。

根Activity的建立

根Activity也就是我們點選桌面圖示的時候,應用程式第一個activity啟動的流程。這裡我側重講解多個程式之間的關係,下面的原始碼也不會講細節,只講解普通activity的建立流程。這裡也相當於一個補充。先看整體流程圖:

根Activity啟動整體流程.png

主要涉及四個程式:

  • Launcher程式,也就是桌面程式
  • 系統服務程式,AMS所在程式
  • Zygote程式,負責建立程式
  • 應用程式程式,也就是即將要啟動的程式

主要流程:

  1. Launcher程式請求AMS建立activity
  2. AMS請求Zygote建立程式。
  3. Zygote通過fork自己來建立程式。並通知AMS建立完成。
  4. AMS通知應用程式建立根Activity。

和普通Activity的建立很像,主要多了建立程式這一步。

原始碼講解

Activity請求AMS的過程

流程圖
Activity請求AMS流程.png
原始碼
  1. 系統通過呼叫Launcher的startActivitySafely方法來啟動應用程式。Launcher是一個類,負責啟動根Activity。

    這一步是根Activity啟動才有的流程,普通啟動是沒有的,放在這裡是作為一點補充而已

    packages/apps/Launcher3/src/com/android/launcher3/Launcher.java/;
    public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
        	//這裡呼叫了父類的方法,繼續檢視父類的方法實現
            boolean success = super.startActivitySafely(v, intent, item);
            ...
            return success;
        }
        
    
    packages/apps/Launcher3/src/com/android/launcher3/BaseDraggingActivity.java/;
    public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
            ...
            // Prepare intent
            //設定標誌singleTask,意味著在新的棧開啟
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            if (v != null) {
                intent.setSourceBounds(getViewBounds(v));
            }
            try {
                boolean isShortcut = Utilities.ATLEAST_MARSHMALLOW
                        && (item instanceof ShortcutInfo)
                        && (item.itemType == Favorites.ITEM_TYPE_SHORTCUT
                        || item.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT)
                        && !((ShortcutInfo) item).isPromise();
                //下面註釋1和註釋2都是直接採用startActivity進行啟動。註釋1會做一些設定
                //BaseDraggingActivity是繼承自BaseActivity,而BaseActivity是繼承自Activity
                //所以直接就跳轉到了Activity的startActivity邏輯。
                if (isShortcut) {
                    // Shortcuts need some special checks due to legacy reasons.
                    startShortcutIntentSafely(intent, optsBundle, item);//1
                } else if (user == null || user.equals(Process.myUserHandle())) {
                    // Could be launching some bookkeeping activity
                    startActivity(intent, optsBundle);//2
                } else {
                    LauncherAppsCompat.getInstance(this).startActivityForProfile(
                            intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
                }
                
               ...
            } 
        	...
            return false;
        }
    
  2. Activity通過Instrumentation來啟動Activity

    /frameworks/base/core/java/android/app/Activity.java/;
    public void startActivity(Intent intent, @Nullable Bundle options) {
        	//最終都會跳轉到startActivityForResult這個方法
            if (options != null) {
                startActivityForResult(intent, -1, options);
            } else {
                // Note we want to go through this call for compatibility with
                // applications that may have overridden the method.
                startActivityForResult(intent, -1);
            }
        }
    
    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
                @Nullable Bundle options) {
        	//mParent是指activityGroup,現在已經採用Fragment代替,這裡會一直是null
        	//下一步會通過mInstrumentation.execStartActivity進行啟動
            if (mParent == null) {
                options = transferSpringboardActivityOptions(options);
                Instrumentation.ActivityResult ar =
                    mInstrumentation.execStartActivity(
                        this, mMainThread.getApplicationThread(), mToken, this,
                        intent, requestCode, options);//1
                if (ar != null) {
                    mMainThread.sendActivityResult(
                        mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                        ar.getResultData());
                }
                ...
            }
        ...
    }
    
  3. Instrumentation請求AMS進行啟動。該類的作用是監控應用程式和系統的互動。到此為止,任務就交給了AMS了,AMS進行一系列處理後,會通過本地的介面IActivityManager來進行回撥啟動activity。

    /frameworks/base/core/java/android/app/Instrumentation.java/;
    public ActivityResult execStartActivity(
                Context who, IBinder contextThread, IBinder token, Activity target,
                Intent intent, int requestCode, Bundle options) {
        ...
        //這個地方比較複雜,先說結論。下面再進行解釋    
        //ActivityManager.getService()獲取到的物件是ActivityManagerService,簡稱AMS
        //通過AMS來啟動activity。AMS是全域性唯一的,所有的活動啟動都要經過他的驗證,執行在獨立的程式中
        //所以這裡是採用AIDL的方式進行跨程式通訊,獲取到的物件其實是一個IBinder介面
            
        //註釋2是進行檢查啟動結果,如果異常則丟擲,如沒有註冊。
        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);//1
                checkStartActivityResult(result, intent);//2
            } catch (RemoteException e) {
                throw new RuntimeException("Failure from system", e);
            }
            return null;
        
    }
    

    這一步是通過AIDL技術進行跨進行通訊。拿到AMS的代理物件,把啟動任務交給了AMS。

    /frameworks/base/core/java/android/app/ActivityManager.java/;
    //單例類
    public static IActivityManager getService() {
    return IActivityManagerSingleton.get();
    }
    
    private static final Singleton<IActivityManager> IActivityManagerSingleton =
    new Singleton<IActivityManager>() {
    @Override
    protected IActivityManager create() {
    //得到AMS的IBinder介面
    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
    //轉化成IActivityManager物件。遠端服務實現了這個介面,所以可以直接呼叫這個
    //AMS代理物件的介面方法來請求AMS。這裡採用的技術是AIDL
    final IActivityManager am = IActivityManager.Stub.asInterface(b);
    return am;
    }
    };
    

AMS處理請求的過程

流程圖
AMS處理啟動Activity流程.png
原始碼
  1. 接下來看AMS的實現邏輯。AMS這部分的原始碼是通過ActivityStartController來建立一個ActivityStarter,然後把邏輯都交給ActivityStarter去執行。ActivityStarter是android 7.0加入的類。

     /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java/;
    //跳轉到startActivityAsUser
    //注意最後多了一個引數UserHandle.getCallingUserId(),表示呼叫者許可權
    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());
    }
    
    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,
                boolean validateIncomingUser) {
            enforceNotIsolatedCaller("startActivity");
    
            userId = mActivityStartController.checkTargetUser(userId, validateIncomingUser,
                    Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
    
            // TODO: Switch to user app stacks here.
        	//這裡通過ActivityStartController獲取到ActivityStarter,通過ActivityStarter來
        	//執行啟動任務。這裡就把任務邏輯給到了AcitivityStarter
            return mActivityStartController.obtainStarter(intent, "startActivityAsUser")
                    .setCaller(caller)
                    .setCallingPackage(callingPackage)
                    .setResolvedType(resolvedType)
                    .setResultTo(resultTo)
                    .setResultWho(resultWho)
                    .setRequestCode(requestCode)
                    .setStartFlags(startFlags)
                    .setProfilerInfo(profilerInfo)
                    .setActivityOptions(bOptions)
                    .setMayWait(userId)
                    .execute();
    
        }
    

    ActivityStartController獲取ActivityStarter

    /frameworks/base/services/core/java/com/android/server/am/ActivityStartController.java/;
    //獲取到ActivityStarter物件。這個物件僅使用一次,當他的execute被執行後,該物件作廢
    ActivityStarter obtainStarter(Intent intent, String reason) {
    return mFactory.obtain().setIntent(intent).setReason(reason);
    }
    
  2. 這部分主要是ActivityStarter的原始碼內容,涉及到的原始碼非常多。AMS把整個啟動邏輯都丟給ActivityStarter去處理了。這裡主要做啟動前處理,建立程式等等。

    /frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java/;
    //這裡需要做啟動預處理,執行startActivityMayWait方法
    int execute() {
            try {
               	...
                if (mRequest.mayWait) {
                    return startActivityMayWait(mRequest.caller, mRequest.callingUid,
                            mRequest.callingPackage, mRequest.intent, mRequest.resolvedType,
                            mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
                            mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
                            mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
                            mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
                            mRequest.inTask, mRequest.reason,
                            mRequest.allowPendingRemoteAnimationRegistryLookup);
                }
                ...
            } 
        	...
        }
    
    //啟動預處理
    private 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 globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
                int userId, TaskRecord inTask, String reason,
                boolean allowPendingRemoteAnimationRegistryLookup) {
            ...
    		//跳轉startActivity
             final ActivityRecord[] outRecord = new ActivityRecord[1];
         	int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
                    voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
                    ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
                    allowPendingRemoteAnimationRegistryLookup);
    }
    
    //記錄啟動程式和activity的資訊
    private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
            SafeActivityOptions options,
            boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
            TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup) {
        ...
        //得到Launcher程式    
        ProcessRecord callerApp = null;
        if (caller != null) {
            callerApp = mService.getRecordForAppLocked(caller);
            ...
        }
        ...
        //記錄得到的activity資訊
        ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
                callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
                resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
                mSupervisor, checkedOptions, sourceRecord);
        if (outActivity != null) {
            outActivity[0] = r;
        }
        ...
        mController.doPendingActivityLaunches(false);
    	//繼續跳轉
        return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
                true /* doResume */, checkedOptions, inTask, outActivity);
    }
    
    //跳轉startActivityUnchecked
    private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
                ActivityRecord[] outActivity) {
        int result = START_CANCELED;
        try {
            mService.mWindowManager.deferSurfaceLayout();
            //跳轉
            result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, doResume, options, inTask, outActivity);
        } 
        ...
        return result;
    }
    
    //主要做與棧相關的邏輯處理,並跳轉到ActivityStackSupervisor進行處理
    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {
        ...
        int result = START_SUCCESS;
        //這裡和我們最初在Launcher設定的標誌FLAG_ACTIVITY_NEW_TASK相關,會建立一個新棧
        if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
                && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
            newTask = true;
            result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack);
        }
        ...
        if (mDoResume) {
            final ActivityRecord topTaskActivity =
                mStartActivity.getTask().topRunningActivityLocked();
            if (!mTargetStack.isFocusable()
                || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                    && mStartActivity != topTaskActivity)) {
                ...
            } else {
                if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
                    mTargetStack.moveToFront("startActivityUnchecked");
                }
                //跳轉到ActivityStackSupervisor進行處理
                mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                                                                mOptions);
            }
        }
    }
    
  3. ActivityStackSupervisor主要負責做activity棧的相關工作,會結合ActivityStack來進行工作。主要判斷activity的狀態,是否處於棧頂或處於停止狀態等

    /frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java/;
    
    boolean resumeFocusedStackTopActivityLocked(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
    	...
        //判斷要啟動的activity是不是出於停止狀態或者Resume狀態
        final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
        if (r == null || !r.isState(RESUMED)) {
            mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
        } else if (r.isState(RESUMED)) {
            // Kick off any lingering app transitions form the MoveTaskToFront operation.
            mFocusedStack.executeAppTransition(targetOptions);
        }
        return false;
    }
    
  4. ActivityStack主要處理activity在棧中的狀態

    /frameworks/base/services/core/java/com/android/server/am/ActivityStack.java/;
    //跳轉resumeTopActivityInnerLocked
    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
        if (mStackSupervisor.inResumeTopActivity) {
            // Don't even start recursing.
            return false;
        }
        boolean result = false;
        try {
            // Protect against recursion.
            mStackSupervisor.inResumeTopActivity = true;
            //跳轉resumeTopActivityInnerLocked
            result = resumeTopActivityInnerLocked(prev, options);
    	...
        } finally {
            mStackSupervisor.inResumeTopActivity = false;
        }
        return result;
    }
    
    //跳轉到StackSupervisor.startSpecificActivityLocked,註釋1
    @GuardedBy("mService")
    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
        ...
        if (next.app != null && next.app.thread != null) {
            ...
        } else {
            ...
            mStackSupervisor.startSpecificActivityLocked(next, true, true);//1
        }     
        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
        return true;
    }
    
  5. 這裡又回到了ActivityStackSupervisor,判斷程式是否已經建立,未建立丟擲異常。然後建立事務交回給本地執行。這裡的事務很關鍵,Activity執行的工作就是這個事務,事務的內容是裡面的item,所以要注意下面的兩個item。

    /frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java/;
    
    void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        //得到即將啟動的activity所在的程式
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);
        getLaunchTimeTracker().setLaunchTime(r);
    
        //判斷該程式是否已經啟動,跳轉realStartActivityLocked,真正啟動活動
        if (app != null && app.thread != null) {
            try {
                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                        || !"android".equals(r.info.packageName)) {
                    app.addPackage(r.info.packageName, r.info.applicationInfo.longVersionCode,
                            mService.mProcessStats);
                }
                realStartActivityLocked(r, app, andResume, checkConfig);//1
                return;
            } 
            ...
        }
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }
    
    
    //主要建立事務交給本地執行
    final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
        boolean andResume, boolean checkConfig) throws RemoteException {
        ...
        //建立啟動activity的事務ClientTransaction物件
        // Create activity launch transaction.
        final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,
                r.appToken);
        // 新增LaunchActivityItem,該item的內容是建立activity
        clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
                System.identityHashCode(r), r.info,
                // TODO: Have this take the merged configuration instead of separate global
                // and override configs.
                mergedConfiguration.getGlobalConfiguration(),
                mergedConfiguration.getOverrideConfiguration(), r.compat,
                r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                r.persistentState, results, newIntents, mService.isNextTransitionForward(),
                profilerInfo));
    
        // Set desired final state.
        //新增執行Resume事務ResumeActivityItem,後續會在本地被執行
        final ActivityLifecycleItem lifecycleItem;
        if (andResume) {
            lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());
        } else {
            lifecycleItem = PauseActivityItem.obtain();
        }
        clientTransaction.setLifecycleStateRequest(lifecycleItem);
    
        // 通過ClientLifecycleManager來啟動事務
        // 這裡的mService就是AMS
        // 記住上面兩個item:LaunchActivityItem和ResumeActivityItem,這是事務的執行單位
        // Schedule transaction.
        mService.getLifecycleManager().scheduleTransaction(clientTransaction);
    }
        
    

    通過AMS獲取ClientLifecycleManager

    /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java/;
    //通過AMS獲取ClientLifecycleManager
    ClientLifecycleManager getLifecycleManager() {
    return mLifecycleManager;
    }
    
  6. ClientLifecycleManager是事務管理類,負責執行事務

    /frameworks/base/services/core/java/com/android/server/am/ClientLifecycleManager.java
    void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        final IApplicationThread client = transaction.getClient();
        //執行事務
        transaction.schedule();
        if (!(client instanceof Binder)) {
            transaction.recycle();
        }
    }
    
  7. 把事務交給本地ActivityThread執行。這裡通過本地ApplicationThread在服務端的介面IApplicationThread來進行跨程式通訊。後面的邏輯就回到了應用程式程式了。

    /frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java/;
    
    //這裡的IApplicationThread是要啟動程式的IBinder介面
    //ApplicationThread是ActivityThread的內部類,IApplicationThread是IBinder代理介面
    //這裡將邏輯轉到本地來執行
    private IApplicationThread mClient;
    public void schedule() throws RemoteException {
        mClient.scheduleTransaction(this);
    }
    

ActivityThread建立Activity的過程

流程圖
ActivityThread響應啟動Activity流程.png
原始碼
  1. IApplicationThread介面的本地實現類ActivityThread的內部類ApplicationThread

    /frameworks/base/core/java/android/app/ActivityThread.java/ApplicationThread.class/;
    //跳轉到ActivityThread的方法實現
    public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        ActivityThread.this.scheduleTransaction(transaction);
    }
    
  2. ActivityThread執行事務。ActivityThread是繼承ClientTransactionHandler,scheduleTransaction的具體實現是在ClientTransactionHandler實現的。這裡的主要內容是把事務傳送給ActivityThread的內部類H去執行。H是一個Handle,通過這個Handle來切到主執行緒執行邏輯。

    /frameworks/base/core/java/android/app/ClientTransactionHandler.java
    void scheduleTransaction(ClientTransaction transaction) {
        //事務預處理
        transaction.preExecute(this);
        //這裡很明顯可以利用Handle機制切換執行緒,下面看看這個方法的實現
        //該方法的具體實現是在ActivityThread,是ClientTransactionHandler的抽象方法
        sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
    }
    
    /frameworks/base/core/java/android/app/ActivityThread.java/;
    final H mH = new H();
    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);
        }
        //利用Handle進行切換。mH是H這個類的例項
        mH.sendMessage(msg);
    }
    
    
  3. H對事務進行處理。呼叫事務池來處理事務

    /frameworks/base/core/java/android/app/ActivityThread.java/H.class
    //呼叫事務池對事務進行處理
    public void handleMessage(Message msg) {
        if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
        switch (msg.what) {
            ...
            case EXECUTE_TRANSACTION:
                final ClientTransaction transaction = (ClientTransaction) msg.obj;
                //呼叫事務池對事務進行處理
                mTransactionExecutor.execute(transaction);
                if (isSystem()) {
                    transaction.recycle();
                }
                // TODO(lifecycler): Recycle locally scheduled transactions.
                break;
                ...
        }
        ...
    }
    
  4. 事務池對事務進行處理。事務池會把事務中的兩個item拿出來分別執行。這兩個事務就是上面我講的兩個Item。對應不同的初始化工作。

    /frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java
        
    public void execute(ClientTransaction transaction) {
        final IBinder token = transaction.getActivityToken();
        log("Start resolving transaction for client: " + mTransactionHandler + ", token: " + token);
    
        //執行事務
        //這兩個事務就是當時在ActivityStackSupervisor中新增的兩個事件(第8步)
        //註釋1執行activity的建立,註釋2執行activity的視窗等等並呼叫onStart和onResume方法
        //後面主要深入註釋1的流程
        executeCallbacks(transaction);//1
        executeLifecycleState(transaction);//2
        mPendingActions.clear();
        log("End resolving transaction");
    }
    
    public void executeCallbacks(ClientTransaction transaction) {
        ...
            //執行事務
            //這裡的item就是當初新增的Item,還記得是哪個嗎?
           	// 對了就是LaunchActivityItem
            item.execute(mTransactionHandler, token, mPendingActions);
            item.postExecute(mTransactionHandler, token, mPendingActions);
        ...
    }
    
    private void executeLifecycleState(ClientTransaction transaction) {
        ...
        // 和上面的一樣,執行事務中的item,item型別是ResumeActivityItem
        lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
        lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
    }
    
    
  5. LaunchActivityItem呼叫ActivityThread執行建立邏輯。

    /frameworks/base/core/java/android/app/servertransaction/LaunchActivityItem.java/;
    
    public void execute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
        ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
                mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
                mPendingResults, mPendingNewIntents, mIsForward,
                mProfilerInfo, client);
        // ClientTransactionHandler是ActivityThread實現的介面,具體邏輯回到ActivityThread
        client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }
    
  6. ActivityThread執行Activity的建立。主要利用Instrumentation來建立activity和回撥activity的生命週期,並建立activity的上下文和app上下文(如果還沒建立的話)。

    /frameworks/base/core/java/android/app/ActivityThread.java/;
    
    public Activity handleLaunchActivity(ActivityClientRecord r,
            PendingTransactionActions pendingActions, Intent customIntent) {
        ...
            // 跳轉到performLaunchActivity
            final Activity a = performLaunchActivity(r, customIntent);
        ...
    }
    
    //使用Instrumentation去建立activity回撥生命週期
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        	//獲取ActivityInfo,使用者儲存程式碼、AndroidManifes資訊。
        	ActivityInfo aInfo = r.activityInfo;
            if (r.packageInfo == null) {
                //獲取apk描述類
                r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                        Context.CONTEXT_INCLUDE_CODE);
            }
        
        	// 獲取activity的包名型別資訊
        	ComponentName component = r.intent.getComponent();
            if (component == null) {
                component = r.intent.resolveActivity(
                    mInitialApplication.getPackageManager());
                r.intent.setComponent(component);
            }
        ...
            // 建立context上下文
            ContextImpl appContext = createBaseContextForActivity(r);
       		// 建立activity
            Activity activity = null;
            try {
                java.lang.ClassLoader cl = appContext.getClassLoader();
                // 通過Instrumentation來建立活動
                activity = mInstrumentation.newActivity(
                        cl, component.getClassName(), r.intent);
                StrictMode.incrementExpectedActivityCount(activity.getClass());
                r.intent.setExtrasClassLoader(cl);
                r.intent.prepareToEnterProcess();
                if (r.state != null) {
                    r.state.setClassLoader(cl);
                }
            }
        ...
            try {
                // 根據包名建立Application,如果已經建立則不會重複建立
                Application app = r.packageInfo.makeApplication(false, mInstrumentation);
                ...
                // 為Activity新增window
                Window window = null;
                if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
                    window = r.mPendingRemoveWindow;
                    r.mPendingRemoveWindow = null;
                    r.mPendingRemoveWindowManager = null;
                }
                appContext.setOuterContext(activity);
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback);
                }
    	...
            // 通過Instrumentation回撥Activity的onCreate方法
            ctivity.mCalled = false;
            if (r.isPersistable()) {
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
    }    
    

    這裡深入來看一下onCreate什麼時候被呼叫

    /frameworks/base/core/java/android/app/Instrumentation.java/;
    public void callActivityOnCreate(Activity activity, Bundle icicle,
      PersistableBundle persistentState) {
    prePerformCreate(activity);
    // 呼叫了activity的performCreate方法
    activity.performCreate(icicle, persistentState);
    postPerformCreate(activity);
    }
    
    /frameworks/base/core/java/android/app/Activity.java/;
    final void performCreate(Bundle icicle, PersistableBundle persistentState) {
    mCanEnterPictureInPicture = true;
    restoreHasCurrentPermissionRequest(icicle);
    // 這裡就回撥了onCreate方法了
    if (persistentState != null) {
      onCreate(icicle, persistentState);
    } else {
      onCreate(icicle);
    }
    ...
    }
    
  7. Instrumentation通過類載入器來建立activity例項

    /frameworks/base/core/java/android/app/Instrumentation.java/;
    
    public Activity newActivity(ClassLoader cl, String className,
            Intent intent)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        String pkg = intent != null && intent.getComponent() != null
                ? intent.getComponent().getPackageName() : null;
        // 利用AppComponentFactory進行例項化
        return getFactory(pkg).instantiateActivity(cl, className, intent);
    }
    
  8. 最後一步,通過AppComponentFactory工廠來建立例項。

    /frameworks/support/compat/src/main/java/androidx/core/app/AppComponentFactory.java
    //其實就相當於直接返回instantiateActivityCompat
    public final Activity instantiateActivity(ClassLoader cl, String className, Intent intent)
        throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        return checkCompatWrapper(instantiateActivityCompat(cl, className, intent));
    }
        
    //泛型方法
    static <T> T checkCompatWrapper(T obj) {
            if (obj instanceof CompatWrapped) {
                T wrapper = (T) ((CompatWrapped) obj).getWrapper();
                if (wrapper != null) {
                    return wrapper;
                }
            }
            return obj;
        }  
    //終於到了盡頭了。利用類載入器來進行例項化。到此activity的啟動就告一段落了。
    public @NonNull Activity instantiateActivityCompat(@NonNull ClassLoader cl,
            @NonNull String className, @Nullable Intent intent)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        try {
            return (Activity) cl.loadClass(className).getDeclaredConstructor().newInstance();
        } catch (InvocationTargetException | NoSuchMethodException e) {
            throw new RuntimeException("Couldn't call constructor", e);
        }
    }
    

小結

上文通過整體流程和程式碼詳解解析了一個activity啟動時的整體流程。不知道讀者們會不會有個疑問:瞭解這些有什麼用呢?日常又用不到。當走完這整個流程的時候,你會發現你對於android又深入瞭解了很多了,面對開發的時候,內心也會更加有自信心,出現的一些bug,可能別人要解決好久,而你,很快就可以解決。另外,這一部分內容在外掛化也有很大的使用,也是學習外掛化必學的知識。

好了講了這麼多,希望以上對你有幫助。有疑問可以評論區或者私信交流一下。另外,博主屬於android新手,如有不對之處還望指正。

參考文獻

相關文章