第九章-四大組件的工作過程(Activity的啓動過程-基於Android9.0源碼)

四大組件的運行狀態

這裏是引用
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

一、Activity的工作過程
Activity作爲很重要的一個組件,其內部工作過程系統做了很多的封裝,這使得啓動一個Activity變得異常簡單。在顯示調用的情況下,只需要通過如下代碼即可完成:

Intent intent = new Intent(this, TestActivity.class);
startActivity(intent);

通過上面的代碼即可啓動一個具體的Activity了,然後新的Activity就會被系統啓動並展示在用戶的眼前。這個過程對於Android開發者再熟悉不過了,這也是很理所當然的事,但是有沒有想過系統內部到底是如何啓動Activity的呢?比如新Activity的對象是在何時創建的?Activity的onCreate方法又是在何時被系統回調的呢?在日常開發中是不需要了解系統的底層工作原理的,但是如果想在技術的領域更上一層樓,就很有必要知道系統的工作原理了。

在這裏插入圖片描述

    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) {//我們只需要關係這部分邏輯即可
            options = transferSpringboardActivityOptions(options);
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);//調用到了Instrumention裏面的execStartActivity方法。
            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);
            }
        }
    }

在這裏插入圖片描述

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 = ActivityTaskManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);//可以看到這裏通過Binder調用到了AMS中去了
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

在這裏插入圖片描述
我們看下ActivityTaskManager.getService()代碼:

    /** @hide */
    public static IActivityTaskManager getService() {
        return IActivityTaskManagerSingleton.get();
    }
    private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
            new Singleton<IActivityTaskManager>() {
                @Override
                protected IActivityTaskManager create() {
                //public static final String ACTIVITY_TASK_SERVICE = "activity_task";
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);//這裏就拿到了服務的Binder類
                    return IActivityTaskManager.Stub.asInterface(b);//和之前的AIDL一樣,將服務端Binder轉化爲IActivityTaskManager,可以直接在本地調用到AMS中的方法了。 
                }
            };

總結:到這裏,啓動的邏輯就通過IPC轉移到了AMS中了。我們只需要看AMS中的startActivity方法即可。
在分析AMS的startActivity方法之前,我們先看下Instrumentation中的execStartActivity方法中有 checkStartActivityResult(result, intent); 這一行代碼。直觀上看這個是檢查activity的啓動結果(實際也是如此的),代碼如下:
在這裏插入圖片描述
從上面的代碼看出,checkStartActivityResult方法作用很明顯,就是檢查啓動Activity的結果。當無法正確啓動一個Activity的時候,就是拋出異常信息。

接着我們繼續分析AMS中的startActivity方法:

    @Override
    public int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
            //public ActivityTaskManagerService mActivityTaskManager;定義
        return mActivityTaskManager.startActivity(caller, callingPackage, intent, resolvedType,
                resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions);
                //可以看到調用到ActivityTaskManagerService 中去了
    }

在這裏插入圖片描述
備註:在Android9.0上的代碼和書上的有些差異,但是流程都差不多。
可以看出,最後又轉移到了ActivityStarter的startActivityMayWait方法中,在startActivityMayWait中又調用了startActivityLocked方法,在startActivityLocked中又調用了startActivityUnchecked,緊接着有調用了resumeTopActivityUncheckedLocked方法,這個時候啓動過程已經從ActivityStackSupervisor轉移到了ActivityStack,可以看如下代碼:

    @GuardedBy("mService")
    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
        if (mInResumeTopActivity) {
            // Don't even start recursing.
            return false;
        }

        boolean result = false;
        try {
            // Protect against recursion.
            mInResumeTopActivity = true;
            result = resumeTopActivityInnerLocked(prev, options);

            // When resuming the top activity, it may be necessary to pause the top activity (for
            // example, returning to the lock screen. We suppress the normal pause logic in
            // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the
            // end. We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here
            // to ensure any necessary pause logic occurs. In the case where the Activity will be
            // shown regardless of the lock screen, the call to
            // {@link ActivityStackSupervisor#checkReadyForSleepLocked} is skipped.
            final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
            if (next == null || !next.canTurnScreenOn()) {
                checkReadyForSleep();
            }
        } finally {
            mInResumeTopActivity = false;
        }

        return result;
    }

上面這段代碼中,resumeTopActivityUncheckedLocked又調用了resumeTopActivityInnerLocked,resumeTopActivityInnerLocked又調用了ActivityStackSupervisor的startSpecificActivityLocked,startSpecificActivityLocked的源碼如下所示:

    void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
        // Is this activity's application already running?
        final WindowProcessController wpc =
                mService.getProcessController(r.processName, r.info.applicationInfo.uid);

        boolean knownToBeDead = false;
        if (wpc != null && wpc.hasThread()) {
            try {
                realStartActivityLocked(r, wpc, andResume, checkConfig);//看這個方法
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting activity "
                        + r.intent.getComponent().flattenToShortString(), e);
            }

            // If a dead object exception was thrown -- fall through to
            // restart the application.
            knownToBeDead = true;
        }

        // Suppress transition until the new activity becomes ready, otherwise the keyguard can
        // appear for a short amount of time before the new process with the new activity had the
        // ability to set its showWhenLocked flags.
        if (getKeyguardController().isKeyguardLocked()) {
            r.notifyUnknownVisibilityLaunched();
        }

        try {
            if (Trace.isTagEnabled(TRACE_TAG_ACTIVITY_MANAGER)) {
                Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "dispatchingStartProcess:"
                        + r.processName);
            }
            // Post message to start process to avoid possible deadlock of calling into AMS with the
            // ATMS lock held.
            final Message msg = PooledLambda.obtainMessage(
                    ActivityManagerInternal::startProcess, mService.mAmInternal, r.processName,
                    r.info.applicationInfo, knownToBeDead, "activity", r.intent.getComponent());
            mService.mH.sendMessage(msg);
        } finally {
            Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
        }
    }

最後又調用了realStartActivityLocked,我們來看下圖瞭解ActivityStack和ActivityStackSupervisor之間的互相傳遞過程
在這裏插入圖片描述

備註:下面的分析是基於Android9.0的代碼分析和書上的代碼有些差異。
在ActivityStackSupervisor.realStartActivityLocked方法中爲ClientTransaction對象添加LaunchActivityItem的callback,然後設置當前的生命週期狀態,最後調用ClientLifecycleManager.scheduleTransaction方法執行。
在這裏插入圖片描述
最終調用到ClientTransaction的schedule方法。

    public void schedule() throws RemoteException {
        mClient.scheduleTransaction(this);//private IApplicationThread mClient;
    }

ClientTransaction.schedule方法的mClient是一個IApplicationThread類型,ActivityThread的內部類ApplicationThread派生這個接口類並實現了對應的方法。所以直接跳轉到ApplicationThread中的scheduleTransaction方法ActivityThread類中並沒有定義scheduleTransaction方法,所以調用的是他父類ClientTransactionHandler的scheduleTransaction方法。

解析說明如下:
在這裏插入圖片描述
ApplicationThread的scheduleTransaction方法:

        @Override
        public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
            ActivityThread.this.scheduleTransaction(transaction);//看到調用了ActivityThread的這個方法
            //而ActivityThread沒有實現該方法,所以調用父類ClientTransactionHandler的這個方法。
            //public final class ActivityThread extends ClientTransactionHandler {
        }

ClientTransactionHandler的方法:(發送了一條消息給ActivityThread)

    /** Prepare and schedule transaction for execution. */
    void scheduleTransaction(ClientTransaction transaction) {
        transaction.preExecute(this);
        sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
    }

在ClientTransactionHandler.scheduleTransaction方法中調用了sendMessage方法,這個方法是一個抽象方法,其實現在ClientTransactionHandler派生類的ActivityThread中。

    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);//定義:final H mH = new H();
    }

ActivityThread.sendMessage方法會把消息發送給內部名字叫H的Handler。
看下H對EXECUTE_TRANSACTION處理方式:

                case EXECUTE_TRANSACTION:
                    final ClientTransaction transaction = (ClientTransaction) msg.obj;
                    mTransactionExecutor.execute(transaction);//看到調用到了execute方法
                    if (isSystem()) {
                        // Client transactions inside system process are recycled on the client side
                        // instead of ClientLifecycleManager to avoid being cleared before this
                        // message is handled.
                        transaction.recycle();
                    }
                    // TODO(lifecycler): Recycle locally scheduled transactions.
                    break;

Handler H的實例接收到EXECUTE_TRANSACTION消息後調用TransactionExecutor.execute方法切換Activity狀態。TransactionExecutor.execute方法裏面先執行Callbacks,然後改變Activity當前的生命週期狀態。

    frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java
    public void execute(ClientTransaction transaction) {
        ...
        executeCallbacks(transaction);
        executeLifecycleState(transaction);
        ...
    }

    public void executeCallbacks(ClientTransaction transaction) {
        if (callbacks == null) {
            // No callbacks to execute, return early.
            return;
        }
        ...
        for (int i = 0; i < size; ++i) {
            final ClientTransactionItem item = callbacks.get(i);
            ...
            item.execute(mTransactionHandler, token, mPendingActions);//這個其實就是執行了我們定義的LaunchActivityItem裏面的execute方法。
            item.postExecute(mTransactionHandler, token, mPendingActions);
            ...
        }
    }

    /** Transition to the final state if requested by the transaction. */
    private void executeLifecycleState(ClientTransaction transaction) {
        ...

        // Cycle to the state right before the final requested state.
        cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */);

        // Execute the final transition with proper parameters.
        lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
        lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
    }

可以看到我們之前在AMS中設置了callback:

	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, proc.getReportedProcState(),
		r.icicle, r.persistentState, results, newIntents,
		dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),
				r.assistToken));


	//clientTransaction的addCallback定義如下:
    public void addCallback(ClientTransactionItem activityCallback) {
        if (mActivityCallbacks == null) {
            mActivityCallbacks = new ArrayList<>();
        }
        mActivityCallbacks.add(activityCallback);
    }

執行callback後跳轉到LaunchActivityItem.execute方法。

    frameworks/base/core/java/android/app/servertransaction/LaunchActivityItem.java
    public void execute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        ...
        client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
    }
    
    frameworks/base/core/java/android/app/ActivityThread.java
    public Activity handleLaunchActivity(ActivityClientRecord r,
            PendingTransactionActions pendingActions, Intent customIntent) {
        ...
        final Activity a = performLaunchActivity(r, customIntent);
        ...
        return a;
    }

可以看到我們最終執行到了ActivitityThread中的performLaunchActivity方法了。

========有個疑問,client.handleLaunchActivity(r, pendingActions, null /* customIntent */);怎麼就調到ActivityThread中的handleLaunchActivity方法呢?

//ActivitityThread中的mTransactionExecutor初始化
private final TransactionExecutor mTransactionExecutor = new TransactionExecutor(this);

//TransactionExecutor的構造
public TransactionExecutor(ClientTransactionHandler clientTransactionHandler) {
    mTransactionHandler = clientTransactionHandler;
}

//這裏就可以看到mTransactionHandler 這個對象就是ActivityThread

//executeCallbacks方法中的代碼,將mTransactionHandler傳遞給了LaunchActivityItem.java中的execute方法。
item.execute(mTransactionHandler, token, mPendingActions);

所以這裏的client.handleLaunchActivity,就是調用的ActivityThread中的handleLaunchActivity方法。

========疑問已解答

到這裏我們的代碼就比較清晰了。看看performLaunchActivity這個方法主要完成的作用。

1.從ActivityClientRecord中獲取待啓動的Activity組件信息

        ActivityInfo aInfo = r.activityInfo;
        if (r.packageInfo == null) {
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);
        }

        ComponentName component = r.intent.getComponent();
        if (component == null) {
            component = r.intent.resolveActivity(
                mInitialApplication.getPackageManager());
            r.intent.setComponent(component);
        }

        if (r.activityInfo.targetActivity != null) {
            component = new ComponentName(r.activityInfo.packageName,
                    r.activityInfo.targetActivity);
        }

2.通過instrumentation的newActivity方法使用類加載器創建Activity對象

        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            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);
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            }
        }

至於instrumentation的newActivity,他的實現就比較簡單,就是通過類加載器創建

    public Activity newActivity(ClassLoader cl, String className,
            Intent intent)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        String pkg = intent != null && intent.getComponent() != null
                ? intent.getComponent().getPackageName() : null;
        return getFactory(pkg).instantiateActivity(cl, className, intent);
    }

3.通過LoadedApk的makeApplicatiton方法來創建Application對象

Application app = r.packageInfo.makeApplication(false, mInstrumentation);
public Application makeApplication(boolean forceDefaultAppClass,
		Instrumentation instrumentation) {
	if (mApplication != null) {
		return mApplication;
	}

	Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");

	Application app = null;

	String appClass = mApplicationInfo.className;
	if (forceDefaultAppClass || (appClass == null)) {
		appClass = "android.app.Application";
	}

	try {
		java.lang.ClassLoader cl = getClassLoader();
		if (!mPackageName.equals("android")) {
			Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
					"initializeJavaContextClassLoader");
			initializeJavaContextClassLoader();
			Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
		}
		ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
		app = mActivityThread.mInstrumentation.newApplication(
				cl, appClass, appContext);
		appContext.setOuterContext(app);
	} catch (Exception e) {
		if (!mActivityThread.mInstrumentation.onException(app, e)) {
			Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
			throw new RuntimeException(
				"Unable to instantiate application " + appClass
				+ ": " + e.toString(), e);
		}
	}
	mActivityThread.mAllApplications.add(app);
	mApplication = app;

	if (instrumentation != null) {
		try {
			instrumentation.callApplicationOnCreate(app);//調用Application的onCreate的方法
		} catch (Exception e) {
			if (!instrumentation.onException(app, e)) {
				Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
				throw new RuntimeException(
					"Unable to create application " + app.getClass().getName()
					+ ": " + e.toString(), e);
			}
		}
	}
...

	return app;
}

在這裏插入圖片描述

4.創建ContextImpl對象並通過Activity的attach方法來完成一些重要數據的初始化
在這裏插入圖片描述

ContextImpl是一個很重要的數據結構,它是Context的具體實現,Context中的大部分邏輯都是ContextImpl來處理的。ContextImpl是通過Activity的attach方法和Activity建立關聯的,除此之外,在attach方法中Activity還會完成Window的創建並且建立自己和Window的關聯。這樣當Window接收到外部輸入的事件後就可以將事件傳遞給Activity。

5.調用Activity的onCreate

	activity.mCalled = false;
	if (r.isPersistable()) {
		mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
	} else {
		mInstrumentation.callActivityOnCreate(activity, r.state);
	}
	if (!activity.mCalled) {
		throw new SuperNotCalledException(
			"Activity " + r.intent.getComponent().toShortString() +
			" did not call through to super.onCreate()");
	}

mInstrumentation.callActivityOnCreate(activity, r.state);,由於Activity的onCreate已經被調用,這也意味着Activity完成了整個啓動過程。

到這裏Activity的啓動過程就分析完成了。我是在Android9.0的源碼下查閱的。和書上的代碼有些差異。但是分析的流程都類似。

總結:整體的啓動大概就是app發起一個啓動activity的請求,通過Binder的IPC過程將啓動交給AMS來處理。AMS中經過多重方法的調用,數據處理。最終也會通過Binder的IPC來回調到週期函數。初始化數據。最終完成整個流程的啓動。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章