中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android?App啟動Activity的方法是什么

發布時間:2022-10-12 09:15:34 來源:億速云 閱讀:94 作者:iii 欄目:開發技術

本文小編為大家詳細介紹“Android App啟動Activity的方法是什么”,內容詳細,步驟清晰,細節處理妥當,希望這篇“Android App啟動Activity的方法是什么”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。

ActivityThread的main方法

讓我們把目光聚焦到ActivityThread的main方法上。

ActivityThread的源碼路徑為 /frameworks/base/core/java/android/app/ActivityThread

public static void main(String[] args) {
      ...
       //請注意這句話,主線程Looper在此處做了prepare的操作
       Looper.prepareMainLooper();
       // Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
       // It will be in the format "seq=114"
       long startSeq = 0;
       if (args != null) {
           for (int i = args.length - 1; i >= 0; --i) {
               if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
                   startSeq = Long.parseLong(
                           args[i].substring(PROC_START_SEQ_IDENT.length()));
               }
           }
       }
       ActivityThread thread = new ActivityThread();
       thread.attach(false, startSeq);
       if (sMainThreadHandler == null) {
           //獲取主線程的handler,其實就是ActivityThread里的mH變量
           sMainThreadHandler = thread.getHandler();
       }
       //開始循環獲取主線程Message消息
       Looper.loop();
       throw new RuntimeException("Main thread loop unexpectedly exited");
   }

繼續從ActivityThread的attach方法往下追蹤。

private void attach(boolean system, long startSeq) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
            //執行此分支
            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                    UserHandle.myUserId());
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            final IActivityManager mgr = ActivityManager.getService();
            try {
                mgr.attachApplication(mAppThread, startSeq);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
            // Watch for getting close to heap limit.
            BinderInternal.addGcWatcher(new Runnable() {
                @Override public void run() {
                    if (!mSomeActivitiesChanged) {
                        return;
                    }
                    Runtime runtime = Runtime.getRuntime();
                    long dalvikMax = runtime.maxMemory();
                    long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
                    if (dalvikUsed > ((3*dalvikMax)/4)) {
                        if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
                                + " total=" + (runtime.totalMemory()/1024)
                                + " used=" + (dalvikUsed/1024));
                        mSomeActivitiesChanged = false;
                        try {
                            ActivityTaskManager.getService().releaseSomeActivities(mAppThread);
                        } catch (RemoteException e) {
                            throw e.rethrowFromSystemServer();
                        }
                    }
                }
            });
        } else {
            ... 
        }
        ViewRootImpl.ConfigChangedCallback configChangedCallback
                = (Configuration globalConfig) -> {
            synchronized (mResourcesManager) {
                // We need to apply this change to the resources immediately, because upon returning
                // the view hierarchy will be informed about it.
                if (mResourcesManager.applyConfigurationToResourcesLocked(globalConfig,
                        null /* compat */)) {
                    updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
                            mResourcesManager.getConfiguration().getLocales());
                    // This actually changed the resources! Tell everyone about it.
                    if (mPendingConfiguration == null
                            || mPendingConfiguration.isOtherSeqNewer(globalConfig)) {
                        mPendingConfiguration = globalConfig;
                        sendMessage(H.CONFIGURATION_CHANGED, globalConfig);
                    }
                }
            }
        };
        ViewRootImpl.addConfigCallback(configChangedCallback);
    }

上述代碼調用了IActivityManagerattachApplication方法,并傳入了當前的ActivityThread對象以及啟動序列號。我們將目光轉向ActivityManagerService

 @Override
   public final void attachApplication(IApplicationThread thread, long startSeq) {
       if (thread == null) {
           throw new SecurityException("Invalid application interface");
       }
       synchronized (this) {
           int callingPid = Binder.getCallingPid();
           final int callingUid = Binder.getCallingUid();
           final long origId = Binder.clearCallingIdentity();
           attachApplicationLocked(thread, callingPid, callingUid, startSeq);
           Binder.restoreCallingIdentity(origId);
       }
   }
 private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
            int pid, int callingUid, long startSeq) {
        ...
            mAtmInternal.preBindApplication(app.getWindowProcessController());
            final ActiveInstrumentation instr2 = app.getActiveInstrumentation();
            if (app.isolatedEntryPoint != null) {
                // This is an isolated process which should just call an entry point instead of
                // being bound to an application.
                thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);
            } else if (instr2 != null) {
                thread.bindApplication(processName, appInfo, providers,
                        instr2.mClass,
                        profilerInfo, instr2.mArguments,
                        instr2.mWatcher,
                        instr2.mUiAutomationConnection, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.isPersistent(),
                        new Configuration(app.getWindowProcessController().getConfiguration()),
                        app.compat, getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial, autofillOptions, contentCaptureOptions);
            } else {
                thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                        null, null, null, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.isPersistent(),
                        new Configuration(app.getWindowProcessController().getConfiguration()),
                        app.compat, getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial, autofillOptions, contentCaptureOptions);
            }
            if (profilerInfo != null) {
                profilerInfo.closeFd();
                profilerInfo = null;
            }
            // Make app active after binding application or client may be running requests (e.g
            // starting activities) before it is ready.
            app.makeActive(thread, mProcessStats);
            checkTime(startTime, "attachApplicationLocked: immediately after bindApplication");
            mProcessList.updateLruProcessLocked(app, false, null);
            checkTime(startTime, "attachApplicationLocked: after updateLruProcessLocked");
            app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
        } catch (Exception e) {
            // todo: Yikes!  What should we do?  For now we will try to
            // start another process, but that could easily get us in
            // an infinite loop of restarting processes...
            Slog.wtf(TAG, "Exception thrown during bind of " + app, e);
            app.resetPackageList(mProcessStats);
            app.unlinkDeathRecipient();
            mProcessList.startProcessLocked(app, new HostingRecord("bind-fail", processName));
            return false;
        }
        // Remove this record from the list of starting applications.
        mPersistentStartingProcesses.remove(app);
        if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES,
                "Attach application locked removing on hold: " + app);
        mProcessesOnHold.remove(app);
        boolean badApp = false;
        boolean didSomething = false;
        // See if the top visible activity is waiting to run in this process...
        if (normalMode) {
            try {
                didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                badApp = true;
            }
        }
        // Find any services that should be running in this process...
        if (!badApp) {
            try {
                didSomething |= mServices.attachApplicationLocked(app, processName);
                checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked");
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
                badApp = true;
            }
        }
        ...
        return true;
    }

上面這段內容有兩段關鍵的語句,一是調用了 IApplicationThreadbindApplication方法;二是調用了ActivityTaskManagerInternalattachApplication方法。我們先來看位于ActivityThread中的bindApplication這個調用。

 public final void bindApplication(String processName, ApplicationInfo appInfo,
                List<ProviderInfo> providers, ComponentName instrumentationName,
                ProfilerInfo profilerInfo, Bundle instrumentationArgs,
                IInstrumentationWatcher instrumentationWatcher,
                IUiAutomationConnection instrumentationUiConnection, int debugMode,
                boolean enableBinderTracking, boolean trackAllocation,
                boolean isRestrictedBackupMode, boolean persistent, Configuration config,
                CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
                String buildSerial, AutofillOptions autofillOptions,
                ContentCaptureOptions contentCaptureOptions) {
            ...
            sendMessage(H.BIND_APPLICATION, data);
        }

方法的結尾,發送了一條what值為H.BIND_APPLICATION的消息。

我們去Handler中找到這條消息的代碼段。

 switch (msg.what) {
                case BIND_APPLICATION:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
                    AppBindData data = (AppBindData)msg.obj;
                    handleBindApplication(data);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
 private void handleBindApplication(AppBindData data) {
        // Register the UI Thread as a sensitive thread to the runtime.
        ...
        Application app;
        try {
            //在這里創建了Application對象
            app = data.info.makeApplication(data.restrictedBackupMode, null);
            // Propagate autofill compat state
            app.setAutofillOptions(data.autofillOptions);
            // Propagate Content Capture options
            app.setContentCaptureOptions(data.contentCaptureOptions);
            mInitialApplication = app;
            // don't bring up providers in restricted mode; they may depend on the
            // app's custom Application class
            if (!data.restrictedBackupMode) {
                if (!ArrayUtils.isEmpty(data.providers)) {
                    installContentProviders(app, data.providers);
                }
            }
            // Do this after providers, since instrumentation tests generally start their
            // test thread at this point, and we don't want that racing.
            try {
                mInstrumentation.onCreate(data.instrumentationArgs);
            }
            catch (Exception e) {
                throw new RuntimeException(
                    "Exception thrown in onCreate() of "
                    + data.instrumentationName + ": " + e.toString(), e);
            }
            try {
                //在這里調用了Application onCreate方法
                mInstrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
                if (!mInstrumentation.onException(app, e)) {
                    throw new RuntimeException(
                      "Unable to create application " + app.getClass().getName()
                      + ": " + e.toString(), e);
                }
            }
        } finally {
            // If the app targets < O-MR1, or doesn't change the thread policy
            // during startup, clobber the policy to maintain behavior of b/36951662
            if (data.appInfo.targetSdkVersion < Build.VERSION_CODES.O_MR1
                    || StrictMode.getThreadPolicy().equals(writesAllowedPolicy)) {
                StrictMode.setThreadPolicy(savedPolicy);
            }
        }
        // 加載字體資源
        FontsContract.setApplicationContextForResources(appContext);
        if (!Process.isIsolated()) {
            try {
                final ApplicationInfo info =
                        getPackageManager().getApplicationInfo(
                                data.appInfo.packageName,
                                PackageManager.GET_META_DATA /*flags*/,
                                UserHandle.myUserId());
                if (info.metaData != null) {
                    final int preloadedFontsResource = info.metaData.getInt(
                            ApplicationInfo.METADATA_PRELOADED_FONTS, 0);
                    if (preloadedFontsResource != 0) {
                        data.info.getResources().preloadFonts(preloadedFontsResource);
                    }
                }
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    }

app = data.info.makeApplication(data.restrictedBackupMode, null);

Application Context對象

這段代碼是一段關鍵代碼,它創建了Application以及全局的Application Context對象, 我們深入往下看一下:

源碼位置為 frameworks/base/core/java/android/app/LoadedApk.java

 public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        if (mApplication != null) {
            return mApplication;
        }
        Application app = null;
        //如果manifest application標簽的name屬性指定了application類,則使用指定的類,否則默認使用android.app.Application
        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);
            }
            //創建全局的Application Context
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            //創建Application對象
            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);
            } 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);
                }
            }
        }
        // Rewrite the R 'constants' for all library apks.
        SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers();
        final int N = packageIdentifiers.size();
        for (int i = 0; i < N; i++) {
            final int id = packageIdentifiers.keyAt(i);
            if (id == 0x01 || id == 0x7f) {
                continue;
            }
            rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
        }
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        return app;
    }
  static public Application newApplication(Class<?> clazz, Context context)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        Application app = (Application)clazz.newInstance();
        //在這里將applicationContext設置到application對象中
        app.attach(context);
        return app;
    }

第一階段,Application的創建與初始化已經至此結束,接下來我們將目光放到ActivityTaskManagerInternalattachApplication方法。

 public boolean attachApplication(WindowProcessController wpc) throws RemoteException {
            synchronized (mGlobalLockWithoutBoost) {
                return mRootActivityContainer.attachApplication(wpc);
            }
        }

進入了RootActivityContainer中繼續執行。

 boolean attachApplication(WindowProcessController app) throws RemoteException {
        final String processName = app.mName;
        boolean didSomething = false;
        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
            final ActivityStack stack = display.getFocusedStack();
            if (stack != null) {
                stack.getAllRunningVisibleActivitiesLocked(mTmpActivityList);
                final ActivityRecord top = stack.topRunningActivityLocked();
                final int size = mTmpActivityList.size();
                for (int i = 0; i < size; i++) {
                    final ActivityRecord activity = mTmpActivityList.get(i);
                    if (activity.app == null && app.mUid == activity.info.applicationInfo.uid
                            && processName.equals(activity.processName)) {
                        try {
                            if (mStackSupervisor.realStartActivityLocked(activity, app,
                                    top == activity /* andResume */, true /* checkConfig */)) {
                                didSomething = true;
                            }
                        } catch (RemoteException e) {
                            Slog.w(TAG, "Exception in new application when starting activity "
                                    + top.intent.getComponent().flattenToShortString(), e);
                            throw e;
                        }
                    }
                }
            }
        }
        if (!didSomething) {
            ensureActivitiesVisible(null, 0, false /* preserve_windows */);
        }
        return didSomething;
    }

ActivityStackSupervisorrealStartActivityLocked方法去真正準備啟動Activity。

 boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
            boolean andResume, boolean checkConfig) throws RemoteException {
        ...
        try {
            ...
            try {
               ...
                // Create activity launch transaction.
                final ClientTransaction clientTransaction = ClientTransaction.obtain(
                        proc.getThread(), r.appToken);
                final DisplayContent dc = r.getDisplay().mDisplayContent;
                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));
                // Set desired final state.
                final ActivityLifecycleItem lifecycleItem;
                if (andResume) {
                    lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());
                } else {
                    lifecycleItem = PauseActivityItem.obtain();
                }
                clientTransaction.setLifecycleStateRequest(lifecycleItem);
                // Schedule transaction.
                mService.getLifecycleManager().scheduleTransaction(clientTransaction);
               ...
            } catch (RemoteException e) {
               ...
            }
        } finally {
            endDeferResume();
        }
        ...
        return true;
    }

為了解釋清楚上述過程,我們必須先得認識一下ClientTransaction及其一系列相關的類。

相關聯的類有以下幾個:ClientTransactionTransactionExecutorClientLifecycleManager以及LaunchActivityItem,我們一個一個來分析。

LaunchActivityItem

LaunchActivityItem實現了BaseClientRequestinterface。這個接口里定義了三個十分重要的方法。

  • preExecute 在請求前進行預處理

  • execute 執行請求

  • postExecute 執行請求后的后續處理 這種設計方式是不是很眼熟!AsyncTask也是基于這種模式設計的,各位讀者不妨自行聯想類比一下。

LaunchActivityItem這個類設計的目的是什么呢?從名字上來講,我們很容易想到,它主要的作用就是用來啟動一個Activity的,具體反應在它重載的excute方法。

 @Override
    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, mAssistToken);
        client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }

看到這句話了么,client.handleLaunchActivity(r, pendingActions, null /* customIntent */);client這個對象是什么?我們可以翻閱一下代碼的調用鏈,可以發現client是一個ActivityThread對象,它最終調用的是ActivityThread中的handleLaunchActivity方法。

除了LauncherActivityItem以外,我們還有abstract的ActivityLifecycleItem類,在這個類中定義了一系列的生命周期狀態,具體如下:

public static final int UNDEFINED = -1;
 public static final int PRE_ON_CREATE = 0;
 public static final int ON_CREATE = 1;
 public static final int ON_START = 2;
 public static final int ON_RESUME = 3;
 public static final int ON_PAUSE = 4;
 public static final int ON_STOP = 5;
 public static final int ON_DESTROY = 6;
 public static final int ON_RESTART = 7;

這些狀態的值基本按照Activity的生命周期的順序,以1為步長遞增定義。為什么這么設計,我們后續會講到。

除此之外,系統還定義了StopActivityItemNewIntentItemDestroyActivityItem等等一系列類似的類,這些類都是為了實現具體的和Activity生命周期有關的任務,并按照 預處理&mdash;&mdash;執行&mdash;&mdash;事后處理 的模板編寫業務。

除此之外,這些類其中有一部分還有一個作用,就是確定客戶端在執行事務后最終應處于的生命周期狀態。

ClientLifecycleManager

生命周期管理類,它能夠組合多個客戶端生命周期變換的請求或回調事務,并將它們作為單個事務執行。這個方法里的內容非常簡單,我們主要來關注一下它的scheduleTransaction的方法。

void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        final IApplicationThread client = transaction.getClient();
        transaction.schedule();
        if (!(client instanceof Binder)) {
            // If client is not an instance of Binder - it's a remote call and at this point it is
            // safe to recycle the object. All objects used for local calls will be recycled after
            // the transaction is executed on client in ActivityThread.
            transaction.recycle();
        }

根據上述源碼,可以看出它調用了傳入的ClientTransactionschedule方法。

ClientTransaction

ClientTransaction是一個保存可以發送到客戶端的消息序列的容器。它包含了三個比較重要的方法, setLifecycleStateRequestaddCallbackschedule,分別用于設置目標生命周期狀態和事務方法,以及執行事務。

我們來看一下schedule這個方法:

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

代碼的內容非常簡單,它將schedule的操作重新分發給了mClient變量,這里的mClient,指的是ActivityThread實例。

public void executeTransaction(ClientTransaction transaction) {
        transaction.preExecute(this);
        getTransactionExecutor().execute(transaction);
        transaction.recycle();
    }

這里首先調用了這樣一條語句,transaction.preExecute(this),用于執行事務前的預處理操作。

  public void preExecute(android.app.ClientTransactionHandler clientTransactionHandler) {
        if (mActivityCallbacks != null) {
            final int size = mActivityCallbacks.size();
            for (int i = 0; i &lt; size; ++i) {
                mActivityCallbacks.get(i).preExecute(clientTransactionHandler, mActivityToken);
            }
        }
        if (mLifecycleStateRequest != null) {
            mLifecycleStateRequest.preExecute(clientTransactionHandler, mActivityToken);
        }
    }

可以看到,它實際調用了通過setLifecycleStateRequestaddCallback兩個方法設置進來的對象的preExecute方法。在實際Activity啟動流程中,對應的是LaunchActivityItemResumeActivityItem兩個類的preExecute方法。

TransactionExecutor

TransactionExecutor是負責管理事務以正確的順序執行的類。

 public void execute(ClientTransaction transaction) {
        ...
        executeCallbacks(transaction);
        executeLifecycleState(transaction);
        mPendingActions.clear();
    }

它首先會通過executeCallbacks方法,執行ClientTransactionadd的所有Callback的executepostExecute方法,具體如下:

  public void executeCallbacks(ClientTransaction transaction) {
       ...
       //獲取目標生命周期狀態
        final ActivityLifecycleItem finalStateRequest = transaction.getLifecycleStateRequest();
        final int finalState = finalStateRequest != null ? finalStateRequest.getTargetState()
                : UNDEFINED;
        // Index of the last callback that requests some post-execution state.
        final int lastCallbackRequestingState = lastCallbackRequestingState(transaction);
        final int size = callbacks.size();
        for (int i = 0; i &lt; size; ++i) {
           ...
            item.execute(mTransactionHandler, token, mPendingActions);
            item.postExecute(mTransactionHandler, token, mPendingActions);
            ...
        }
    }

讓我們回到Activity的啟動流程的代碼中,clientTransaction加入了一個Callback&mdash;&mdash;&mdash;&mdash;LaunchActivityItem,從上文可以知,這個類的execute方法里有這么一段代碼client.handleLaunchActivity(r, pendingActions, null /* customIntent */);,去負責啟動Activity。

executeLifecycleState方法

  private void executeLifecycleState(ClientTransaction transaction) {
        final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
        final IBinder token = transaction.getActivityToken();
        final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
        if (r == null) {
            //第一次啟動獲得的r為null,實際上會走此分支,只有在performLaunchActivity方法調用后,r才不為null
            return;
        }
        // Cycle to the state right before the final requested state.
        cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */, transaction);
        // Execute the final transition with proper parameters.
        lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
        lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
    }

我們重點關注一下cycleToPath方法:

 private void cycleToPath(ActivityClientRecord r, int finish, boolean excludeLastState,
            ClientTransaction transaction) {
        final int start = r.getLifecycleState();
        if (DEBUG_RESOLVER) {
            Slog.d(TAG, tId(transaction) + "Cycle activity: "
                    + getShortActivityName(r.token, mTransactionHandler)
                    + " from: " + getStateName(start) + " to: " + getStateName(finish)
                    + " excludeLastState: " + excludeLastState);
        }
        final IntArray path = mHelper.getLifecyclePath(start, finish, excludeLastState);
        performLifecycleSequence(r, path, transaction);
    }

mHelper.getLifecyclePath(start, finish, excludeLastState):根據當前Activity所處的狀態與目標生命周期狀態,生成一個包含該狀態區間內所有狀態的Int數組。

  private void performLifecycleSequence(ActivityClientRecord r, IntArray path,
            ClientTransaction transaction) {
        final int size = path.size();
        for (int i = 0, state; i < size; i++) {
            state = path.get(i);
            if (DEBUG_RESOLVER) {
                Slog.d(TAG, tId(transaction) + "Transitioning activity: "
                        + getShortActivityName(r.token, mTransactionHandler)
                        + " to state: " + getStateName(state));
            }
            switch (state) {
                case ON_CREATE:
                    mTransactionHandler.handleLaunchActivity(r, mPendingActions,
                            null /* customIntent */);
                    break;
                case ON_START:
                    mTransactionHandler.handleStartActivity(r, mPendingActions);
                    break;
                case ON_RESUME:
                    mTransactionHandler.handleResumeActivity(r.token, false /* finalStateRequest */,
                            r.isForward, "LIFECYCLER_RESUME_ACTIVITY");
                    break;
                case ON_PAUSE:
                    mTransactionHandler.handlePauseActivity(r.token, false /* finished */,
                            false /* userLeaving */, 0 /* configChanges */, mPendingActions,
                            "LIFECYCLER_PAUSE_ACTIVITY");
                    break;
                case ON_STOP:
                    mTransactionHandler.handleStopActivity(r.token, false /* show */,
                            0 /* configChanges */, mPendingActions, false /* finalStateRequest */,
                            "LIFECYCLER_STOP_ACTIVITY");
                    break;
                case ON_DESTROY:
                    mTransactionHandler.handleDestroyActivity(r.token, false /* finishing */,
                            0 /* configChanges */, false /* getNonConfigInstance */,
                            "performLifecycleSequence. cycling to:" + path.get(size - 1));
                    break;
                case ON_RESTART:
                    mTransactionHandler.performRestartActivity(r.token, false /* start */);
                    break;
                default:
                    throw new IllegalArgumentException("Unexpected lifecycle state: " + state);
            }
        }
    }

performLifecycleSequence開始負責按順序執行IntArray區間里的狀態變換。

讓我們重新回到Activity的啟動流程上,從handleLaunchActivity繼續往下追蹤:

 public Activity handleLaunchActivity(ActivityClientRecord r,
      ...
        final Activity a = performLaunchActivity(r, customIntent);
      ...
    }
  private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        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);
        }
        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            //通過newInstance創建Activity實例
            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);
            }
        }
        try {
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);
            if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
            if (localLOGV) Slog.v(
                    TAG, r + ": app=" + app
                    + ", appName=" + app.getPackageName()
                    + ", pkg=" + r.packageInfo.getPackageName()
                    + ", comp=" + r.intent.getComponent().toShortString()
                    + ", dir=" + r.packageInfo.getAppDir());
            if (activity != null) {
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);
                if (r.overrideConfig != null) {
                    config.updateFrom(r.overrideConfig);
                }
                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                        + r.activityInfo.name + " with config " + config);
                Window window = null;
                if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
                    window = r.mPendingRemoveWindow;
                    r.mPendingRemoveWindow = null;
                    r.mPendingRemoveWindowManager = null;
                }
                appContext.setOuterContext(activity);
                //調用attach方法,開始初始化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,
                        r.assistToken);
                if (customIntent != null) {
                    activity.mIntent = customIntent;
                }
                r.lastNonConfigurationInstances = null;
                checkAndBlockForNetworkAccess();
                activity.mStartedActivity = false;
                int theme = r.activityInfo.getThemeResource();
                if (theme != 0) {
                    activity.setTheme(theme);
                }
                activity.mCalled = false;
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    //調用Activity的onCreate方法
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                if (!activity.mCalled) {
                    throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                        " did not call through to super.onCreate()");
                }
                r.activity = activity;
            }
            r.setState(ON_CREATE);
            // updatePendingActivityConfiguration() reads from mActivities to update
            // ActivityClientRecord which runs in a different thread. Protect modifications to
            // mActivities to avoid race.
            synchronized (mResourcesManager) {
                mActivities.put(r.token, r);
            }
        } catch (SuperNotCalledException e) {
            throw e;
        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to start activity " + component
                    + ": " + e.toString(), e);
            }
        }
        return activity;
    }

Application app = r.packageInfo.makeApplication(false, mInstrumentation);

有些讀者可能會對這句話有些疑問,前面不是已經創建過Application對象了嗎,怎么這里還調用一遍,不是說一個進程里只能有一個Application對象嗎?

我們進入makeApplication方法里看一下,第一句話就解釋了原因:

  if (mApplication != null) {
            return mApplication;
        }

所以說,并不會重復創建,這里只是將之前已創建的Application重新獲取一下而已。

mInstrumentation.callActivityOnCreate(activity, r.state);語句的調用,標識著Activity進入onCreate流程,接下來便是Ui的繪制與展示的流程,在此便不做展開分析了。

文章的最后,我們用一個簡單的圖表對這一篇activity的啟動流程做一個總結,并留給各位讀者一個面試中高頻次問題:請簡述一下Activity的啟動流程? 看看各位讀者能不能總結歸納出一個比較好的答案。

[ActivityThread.java]
main()
attach()
   |
[ActivityManagerService.java]
attachApplication()
attachApplicationLocked()
	|		 |
	|	[ActivityThread.java]	
	|	 bindApplication()			//發送了H.BIND_APPLICATION消息
	|      handleBindApplication()	                //創建Application實例,并調用onCreate方法
	|                 |
	|	  [LoadedApk.java]
	|	  makeApplication()
[ActivityTaskManagerService.java]
attachApplication()
	|
[RootActivityContainer.java]
attachApplication()
	|
[ActivityStackSupervisor.java]
realStartActivityLocked()
	|
[ClientLifecycleManager.java]
scheduleTransaction()
	|
[ClientTransaction.java]
schedule()
	|
[ActivityThread.java]
executeTransaction()
	|
[TransactionExecutor.java]
execute()
executeCallbacks()
	|	
[LaunchActivityItem.java]	
execute()
	|
[ActivityThread.java]
handleLaunchActivity()
performLaunchActivity()			        //創建Activity實例,調用activity attach和onCreate方法

讀到這里,這篇“Android App啟動Activity的方法是什么”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

织金县| 射阳县| 阜城县| 新民市| 田东县| 思茅市| 翁牛特旗| 康定县| 永春县| 宜君县| 四平市| 武鸣县| 山丹县| 青龙| 怀柔区| 东明县| 孟津县| 含山县| 内黄县| 南乐县| 新田县| 揭西县| 西畴县| 原阳县| 芜湖县| 夏河县| 徐水县| 贵州省| 信阳市| 曲周县| 巴马| 溆浦县| 峨边| 冷水江市| 鞍山市| 日喀则市| 平江县| 达拉特旗| 宁都县| 万山特区| 徐汇区|