主頁 > 移動端開發 > Android之Activity啟動流程詳解(基于api28)

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

2020-12-13 07:25:59 移動端開發

前言

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新手,如有不對之處還望指正,

參考文獻

  • 《Android進階解密》
  • 《Android開發藝術探索》
  • Android進階(四):Activity啟動程序(最詳細&最簡單)

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/233878.html

標籤:Android

上一篇:QT5發布后sqlite創建不了資料庫???

下一篇:Android之Activity啟動流程詳解(基于api28)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more