国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

android源碼學(xué)習(xí)- APP啟動(dòng)流程(android12源碼)

這篇具有很好參考價(jià)值的文章主要介紹了android源碼學(xué)習(xí)- APP啟動(dòng)流程(android12源碼)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

前言:

百度一搜能找到很多講APP啟動(dòng)流程的,但是往往要么就是太老舊(還是基于android6去分析的),要么就是不全(往往只講了整個(gè)流程的一小部分)。所以我結(jié)合網(wǎng)上現(xiàn)有的文章,以及源碼的閱讀和調(diào)試,耗費(fèi)了3整天的時(shí)間,力求寫出一篇最完整,最詳細(xì),最通俗易懂的文章,來講清楚在android上,APP是如何啟動(dòng)的。

?該文屬于安卓源碼探究專欄中的文章,專欄中很多類似源碼分析的文章,歡迎大家閱讀。

鏈接如下:

安卓源碼研究

一、APP啟動(dòng)流程概覽

涉及到四個(gè)進(jìn)程之間的通信,分別是Laucher進(jìn)程(桌面APP),SystemServer進(jìn)程(AMS所屬進(jìn)程),Zygote進(jìn)程(系統(tǒng)和所有APP的創(chuàng)建進(jìn)程),APP進(jìn)程。

APP簡(jiǎn)要的啟動(dòng)流程是這樣的:
1.Laucher進(jìn)程會(huì)通過binder的方式通知SystemServer進(jìn)程。

2.然后SystemServer進(jìn)程中的AMS會(huì)查詢對(duì)應(yīng)的Activity棧信息,如果對(duì)應(yīng)APP進(jìn)程不存在則會(huì)加載占位圖。然后通過socket的方式通知Zygote去創(chuàng)建APP進(jìn)程。

3.APP進(jìn)程創(chuàng)建后會(huì)執(zhí)行main方法,然后通知AMS

4.AMS收到信息后會(huì)繼續(xù)通知APP去創(chuàng)建Application,并且接下來會(huì)通知APP進(jìn)程取拉起Activity。

5.APP進(jìn)程依次收到通知后,會(huì)依次完成加載APK,初始化Application,執(zhí)行Activtiy生命周期等操作。最終會(huì)把首屏展示出來。

流程圖如下,建議雙擊放大后觀看:

android源碼學(xué)習(xí)- APP啟動(dòng)流程(android12源碼)

?

接下來的幾章,會(huì)按照上面的流程逐一拆解分析:

二、Launcher通知AMS啟動(dòng)APP

Launcher進(jìn)程其實(shí)和普通APP是一樣的,甚至我們可以把自己的APP設(shè)置為桌面APP。

2.1 Launcher獲取到AMS的binder

而Launcher通知AMS的流程和正常APP也是一樣的,通過ServiceManager獲取到AMS的binder引用。這里提到了ServiceManager,其實(shí)ServiceManagerService也是單獨(dú)的一個(gè)進(jìn)程,其存儲(chǔ)了所有APP所需要的binder引用。而且其地址是固定的,所以獲取ServiceManager可以直接獲取。

2.2 通知ActivityManagerService

Launcher通過上述獲取到的binder通知到AMS,調(diào)用的方式是startActivityWithFeature。

而由于AMS實(shí)現(xiàn)了IActivityManager.Stub的實(shí)現(xiàn),所以其startActivityWithFeature方法會(huì)收到launcher發(fā)過來的通知。

2.3?系統(tǒng)進(jìn)程加載占位圖

AMS中,會(huì)交由ActivityTaskManagerService去進(jìn)行對(duì)應(yīng)啟動(dòng)任務(wù)的處理。最終會(huì)交給ActivityStart進(jìn)行處理。

ActivityStart中,首先會(huì)進(jìn)行一個(gè)邏輯判斷,如果進(jìn)程不存在,則首先會(huì)加載APP中MainActivity的主題作為背景圖,顯示到屏幕上。這一步操作是發(fā)生在SystemServer進(jìn)程的,APP進(jìn)程還未創(chuàng)建。

android11開始支持啟動(dòng)動(dòng)畫,邏輯也是在這里處理的。

2.4 AMS進(jìn)行啟動(dòng)操作

一個(gè)進(jìn)程中會(huì)有多個(gè)任務(wù)棧,棧對(duì)應(yīng)的是Task類。

一個(gè)任務(wù)棧中會(huì)有多個(gè)Activity對(duì)象,這個(gè)Activity對(duì)象在AMS中使用ActivityRecord記錄。

這一塊的具體邏輯,我會(huì)單獨(dú)寫一篇Activity的啟動(dòng)邏輯來進(jìn)行描述。

這里暫時(shí)先簡(jiǎn)單描述下,如果AMS發(fā)現(xiàn)進(jìn)程不存在,會(huì)去通知Zygote的進(jìn)行進(jìn)程fork就好,對(duì)應(yīng)的fork邏輯在下一章。

三、Zygote創(chuàng)建APP進(jìn)程

3.1 AMS中內(nèi)部邏輯執(zhí)行

ActivityTaskManagerService調(diào)用startProcessAsync方法會(huì)去負(fù)責(zé)創(chuàng)建APP進(jìn)程,這是異步的,通過handler轉(zhuǎn)發(fā)后最終會(huì)調(diào)用到LocalService.startProcess()方法。

然后會(huì)通知到ProcessList.startProcessLocked方法,這個(gè)方法中,會(huì)構(gòu)造一個(gè)對(duì)象ProcessRecord對(duì)象,然后把各種信息添加到這個(gè)對(duì)象中。

接下來會(huì)調(diào)用到ProcessList.startProcessLocked這個(gè)方法,這個(gè)方法主要是負(fù)責(zé)把各種信息轉(zhuǎn)換為runtimeFlags標(biāo)記位,連同上面構(gòu)造的ProcessRecord繼續(xù)傳入下一層。

最終通知到Process.start方法,然后交由ZygoteProcess.start方法,最終傳遞到startViaZygote方法。

3.2 請(qǐng)求參數(shù)拼接成字符串發(fā)送給Zygote

startViaZygote這個(gè)方法中,會(huì)把各種配置參數(shù)拼接為字符串。

最終在ZygoteProcess.attemptUsapSendArgsAndGetResult方法中,通過LocalSocket的方式把上面拼接的字符串內(nèi)容傳遞給Zygote進(jìn)程。并且從socket中讀取返回值,返回值的PID>0則證明進(jìn)程創(chuàng)建成功。

3.3?Zygote進(jìn)程邏輯

在了解Zygote進(jìn)程如何解析AMS發(fā)送過來的請(qǐng)求之前,我們先簡(jiǎn)單了解下Zygote進(jìn)程創(chuàng)建后的一些基本邏輯。如下圖:

android源碼學(xué)習(xí)- APP啟動(dòng)流程(android12源碼)

一。Zygote進(jìn)程創(chuàng)建后,最開始的入口是在C層,app_main.cpp文件的main方法(該進(jìn)程由Init進(jìn)程啟動(dòng),這里就不擴(kuò)展了),在main方法中會(huì)配置一些JVM的參數(shù),這個(gè)和JAVA的虛擬機(jī)參數(shù)配置類似。最終會(huì)調(diào)用到AndroidRuntime.cpp中的start函數(shù),去啟動(dòng)JVM虛擬機(jī)。

 if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
        return;
    }

二。虛擬機(jī)創(chuàng)建之后,會(huì)通過native層反射找到main函數(shù),并調(diào)用ZygoteInit類的main函數(shù)。

AndroidRumtime.cpp的start方法中:

if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
            /* keep going */
        } else {
            env->CallStaticVoidMethod(startClass, startMeth, strArray);

#if 0
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
#endif
        }
    }

三。ZygoteInit類的main方法中,會(huì)做如下幾件事:

第一步,把自身的進(jìn)程ID設(shè)置為0,并且沒有parent進(jìn)程。

第二步,會(huì)進(jìn)行一系列的初始化操作,比如加載native環(huán)境,加載JVM環(huán)境,加載系統(tǒng)類,加載系統(tǒng)資源等等。都在其preload方法中。

第三步,如果是首次執(zhí)行,則會(huì)創(chuàng)建SystemServer進(jìn)程。這也是Zygote進(jìn)程的大兒子。AMS,WMS都屬于SystemServer進(jìn)程。

第四步,會(huì)創(chuàng)建zygoteServer對(duì)象,并且調(diào)用其runSelectLoop方法。監(jiān)聽socket不斷的接傳遞過來的信息

第五步,Zygote進(jìn)程的fork,其實(shí)是復(fù)制一個(gè)原原本本的自己。runSelectLoop方法中其實(shí)會(huì)去執(zhí)行fork操作,這個(gè)后面會(huì)講,我們這里只需要知道,執(zhí)行到caller.run();這一句的時(shí)候,已經(jīng)處于APP進(jìn)程狀態(tài)了。

public static void main(String[] argv) {
        ZygoteServer zygoteServer = null;

        // Mark zygote start. This ensures that thread creation will throw
        // an error.
        ZygoteHooks.startZygoteNoThreadCreation();

        // Zygote goes into its own process group.
        try {
            Os.setpgid(0, 0);
        } catch (ErrnoException ex) {
            throw new RuntimeException("Failed to setpgid(0,0)", ex);
        }

        
            
        ...
         
            if (!enableLazyPreload) {
                bootTimingsTraceLog.traceBegin("ZygotePreload");
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                        SystemClock.uptimeMillis());
                //2.初始化操作
                preload(bootTimingsTraceLog);
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                        SystemClock.uptimeMillis());
                bootTimingsTraceLog.traceEnd(); // ZygotePreload
            }

            // Do an initial gc to clean up after startup
            bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
            gcAndFinalize();
            bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC

            bootTimingsTraceLog.traceEnd(); // ZygoteInit

            Zygote.initNativeState(isPrimaryZygote);

            ZygoteHooks.stopZygoteNoThreadCreation();

            zygoteServer = new ZygoteServer(isPrimaryZygote);

            if (startSystemServer) {
                //3.首次啟動(dòng)時(shí),會(huì)啟動(dòng)系統(tǒng)進(jìn)程
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);

                // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
                // child (system_server) process.
                if (r != null) {
                    r.run();
                    return;
                }
            }

             //4.啟動(dòng)無限循環(huán)監(jiān)聽socket
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with fatal exception", ex);
            throw ex;
        } finally {
            if (zygoteServer != null) {
                zygoteServer.closeServerSocket();
            }
        }

        // We're in the child process and have exited the select loop. Proceed to execute the
        // command.
        if (caller != null) {
            //5.這里的調(diào)用已經(jīng)是在APP進(jìn)程了,zygote進(jìn)程永遠(yuǎn)不會(huì)執(zhí)行到這里
            caller.run();
        }
    }

3.4 收到通知后去fork產(chǎn)生APP進(jìn)程

runSelectLoop方法中,會(huì)開啟一個(gè)無限循環(huán)。如果收到了消息

如果收到了消息,則會(huì)調(diào)用ZygoteConnection.processCommand去處理。

Runnable runSelectLoop (String abiList){
//        ...

            while (true) {
//            ...
                try {
                    ZygoteConnection connection = peers.get(pollIndex);
                    boolean multipleForksOK = !isUsapPoolEnabled()
                            && ZygoteHooks.isIndefiniteThreadSuspensionSafe();
                    //收到消息,處理消息并且返回runnable。
                    final Runnable command =
                            connection.processCommand(this, multipleForksOK);

                    // TODO (chriswailes): Is this extra check necessary?
                    if (mIsForkChild) {
                        if (command == null) {
                            throw new IllegalStateException("command == null");
                        }
                         //子進(jìn)程執(zhí)行,子進(jìn)程的mIsForkChild會(huì)被設(shè)置為true,則返回command
                        return command;
                    } else {
                         //Zygote進(jìn)程執(zhí)行,則繼續(xù)執(zhí)行循環(huán)
                        //       ...
                    }
                }
            }
        }

而在processCommand中,會(huì)解析收到的參數(shù),最終調(diào)用Zygote.forkAndSpecialize去fork一個(gè)新進(jìn)程。這個(gè)方法雖然只會(huì)調(diào)用一次,返回因?yàn)檫M(jìn)程是拷貝的,所以實(shí)際上會(huì)有兩次返回,返回兩個(gè)pid。pid為0時(shí)為子進(jìn)程,設(shè)置標(biāo)記為子進(jìn)程。反之仍就還是Zygote進(jìn)程。

 pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid,
                            parsedArgs.mGids, parsedArgs.mRuntimeFlags, rlimits,
                            parsedArgs.mMountExternal, parsedArgs.mSeInfo, parsedArgs.mNiceName,
                            fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
                            parsedArgs.mInstructionSet, parsedArgs.mAppDataDir,
                            parsedArgs.mIsTopApp, parsedArgs.mPkgDataInfoList,
                            parsedArgs.mAllowlistedDataInfoList, parsedArgs.mBindMountAppDataDirs,
                            parsedArgs.mBindMountAppStorageDirs);

                    try {
                        if (pid == 0) {
                            // in child
                            zygoteServer.setForkChild();

                            zygoteServer.closeServerSocket();
                            IoUtils.closeQuietly(serverPipeFd);
                            serverPipeFd = null;

                            return handleChildProc(parsedArgs, childPipeFd,
                                    parsedArgs.mStartChildZygote);
                        } else {
                            // In the parent. A pid < 0 indicates a failure and will be handled in
                            // handleParentProc.
                            IoUtils.closeQuietly(childPipeFd);
                            childPipeFd = null;
                            handleParentProc(pid, serverPipeFd);
                            return null;
                        }
                    } finally {
                        IoUtils.closeQuietly(childPipeFd);
                        IoUtils.closeQuietly(serverPipeFd);
                    }

3.5?調(diào)用ActivityThread.main方法

調(diào)用到handleChildProc方法時(shí),已經(jīng)處于APP進(jìn)程的狀態(tài)。

該方法掉調(diào)用到ZygoteInit.zygoteInit()方法,相關(guān)代碼如下:

    public static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader) {
        ...
        RuntimeInit.redirectLogStreams();
        RuntimeInit.commonInit();
        ZygoteInit.nativeZygoteInit();
        return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
                classLoader);
    }

第一步,把System.out的輸出重定向到Logcat中;

第二步,在commonInit方法中,設(shè)置Thread的UncaughtExceptionPreHandler和DefaultUncaughtExceptionHandler。用于應(yīng)用發(fā)生異常時(shí)的處理,這里稍微擴(kuò)展下,DefaultUncaughtExceptionHandler設(shè)置的是RuntimeInit.KillApplicationHandler,所以所有最終未處理的異常都會(huì)走到這個(gè)類中。

第三步,native中進(jìn)行相關(guān)的初始化。

最后一步,做VM虛擬機(jī)的一些配置,然后就會(huì)調(diào)用findStaticMain方法。

接下來,我們看下findStaticMain方法:

protected static Runnable findStaticMain(String className, String[] argv,
            ClassLoader classLoader) {
        Class<?> cl;

        try {
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        }

        Method m;
        try {
            m = cl.getMethod("main", new Class[] { String[].class });
        } catch (NoSuchMethodException ex) {
            throw new RuntimeException(
                    "Missing static main on " + className, ex);
        } catch (SecurityException ex) {
            throw new RuntimeException(
                    "Problem getting static main on " + className, ex);
        }

        int modifiers = m.getModifiers();
        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
            throw new RuntimeException(
                    "Main method is not public and static on " + className);
        }

        /*
         * This throw gets caught in ZygoteInit.main(), which responds
         * by invoking the exception's run() method. This arrangement
         * clears up all the stack frames that were required in setting
         * up the process.
         */
        return new MethodAndArgsCaller(m, argv);
    }

這里只看到出現(xiàn)了main方法,并沒有看到ActivityThread類的聲明。所以,是如何最終選擇啟動(dòng)類類中的main方法呢?其實(shí)原理很簡(jiǎn)單,這個(gè)方法中有一個(gè)className參數(shù),這個(gè)其實(shí)就是ActivityThread類,它是通過socket傳遞過來的一個(gè)參數(shù),其定義在ProcessList的startProcessLocked方法中

所以最后返回的其實(shí)是一個(gè)runnable接口實(shí)現(xiàn)類,而這個(gè)runnable中實(shí)現(xiàn)了調(diào)用ActivityThread中main方法的邏輯。

還記得3.3中Zygote創(chuàng)建后的邏輯嗎?最后一句是調(diào)用?caller.run();

是的,這個(gè)caller就是最后返回的runnable接口實(shí)現(xiàn)類,去完成調(diào)用main方法的操作。

四、APP進(jìn)程創(chuàng)建初始化操作

app進(jìn)程初始化的操作比較簡(jiǎn)單,主要做了兩件事,初始化looper,以及通知AMS。(注意,這里只是APP進(jìn)程創(chuàng)建了,但是還沒有加載APK中的任何類)

4.1 初始化MainLooper

調(diào)用main方法的線程,會(huì)被設(shè)置為主線程,Looper此時(shí)會(huì)開啟無限循環(huán)。

main(){
    //looper綁定主線程
    Looper.prepareMainLooper();

    //通知AMS
    ActivityThread thread = new ActivityThread();
    thread.attach(false, startSeq);

    //looper開啟無限循環(huán)讀取消息
    Looper.loop();
}

4.2 通知AMS

ActivityThread.attach方法中,實(shí)現(xiàn)邏輯也是比較簡(jiǎn)單的,直接通過binder通知AMS,并且把自身的binder(ApplicationThread)也傳遞給AMS。

            final IActivityManager mgr = ActivityManager.getService();
            try {
                mgr.attachApplication(mAppThread, startSeq);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }

這里AMS的binder是直接通過ServierManager的方式獲取的。ServierManager存儲(chǔ)了所有的binder引用,注冊(cè)的形式,AMS在啟動(dòng)的時(shí)候去注冊(cè)。

五、AMS通知APP進(jìn)程進(jìn)行各種生命周期操作

5.1 喚起APP初始化并拉起APP首屏

ActivityManagerService的attachApplication方法會(huì)收到APP傳遞過來的消息,然后交由attachApplicationLocked處理。

attachApplicationLocked中主要負(fù)責(zé)兩件事:

1.通知APP進(jìn)程進(jìn)行初始化操作;

2.進(jìn)行一些列操作,最終通知APP拉起指定的MainActivity。

說到這,問一個(gè)問題1,為什么明明是串行通知APP去執(zhí)行的,而APP那邊不會(huì)出現(xiàn)先加載Activity,再去初始化應(yīng)用的情況呢?答案在下一小節(jié)。

 @GuardedBy("this")
    private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
            int pid, int callingUid, long startSeq) {
        ...
            if (app.getIsolatedEntryPoint() != null) {
                ...
            } else if (instr2 != null) {
                //1通知APP進(jìn)行初始化操作
                thread.bindApplication(processName, appInfo, providerList,
                        instr2.mClass,
                        profilerInfo, instr2.mArguments,
                        instr2.mWatcher,
                        instr2.mUiAutomationConnection, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.isPersistent(),
                        new Configuration(app.getWindowProcessController().getConfiguration()),
                        app.getCompat(), getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial, autofillOptions, contentCaptureOptions,
                        app.getDisabledCompatChanges(), serializedSystemFontMap);
            } else {
                ...
                同上
            }
        ...
        // 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;
            }
        }
        ...
        return true;
    }

5.2?APP進(jìn)行初始化操作

ActivityThread中ApplicationThread的bindApplication會(huì)收到通知,通過handler交給主線程去處理。所以我們也就知道上面問題1的答案了,無論是初始化APP,還是拉起Activity,都是最終交給Handler切換到主線程處理的。所以哪怕初始化APP是耗時(shí)操作,拉起Activity的任務(wù)也得排隊(duì)等到前面任務(wù)執(zhí)行完了才能執(zhí)行。

最終通過handler是交給handleBindApplciation去完成APP的初始化邏輯的。主要包含下面幾個(gè)操作:

1.使用classLoader去加載APK中的DEX文件。

2.加載APK中的資源。

3.反射生成Application類,并調(diào)用其attachBaseApplication方法。

4.調(diào)用Application的onCreate方法。

@UnsupportedAppUsage
    private void handleBindApplication(AppBindData data) {
        //1.classLoader加載APK中的dex,并且加載APK的資源
        final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);

        // Continue loading instrumentation.
        //2.生成代理類
        mInstrumentation = new Instrumentation();
        mInstrumentation.basicInit(this);
        // Allow disk access during application and provider setup. This could
        // block processing ordered broadcasts, but later processing would
        // probably end up doing the same disk access.
        Application app;
        //3.聲明application
        app = data.info.makeApplication(data.restrictedBackupMode, null);
            ...
        //4.調(diào)用Application的onCreate
        mInstrumentation.onCreate(data.instrumentationArgs);

    }

onCreate創(chuàng)建完成后并不會(huì)通知AMS,因?yàn)閍ctivity的拉起操作和初始化Application在AMS中是串行的。

5.3 AMS中處理Activity啟動(dòng)邏輯

5.1中講到attachApplicationLocked會(huì)最終通知APP去拉起Activity,那么整個(gè)流程是怎樣的呢?

會(huì)執(zhí)行下面這樣的調(diào)用順序。

ActivityManagerService.attachApplicationLocked->

ActivityTaskManagerService.LocalService.attachApplication->

RootWindowContainer.attachApplication->

RootWindowContainer.startActivityForAttachedApplicationIfNeeded->

ActivityTaskSupervisor.realStartActivityLocked

到了realStartActivityLocked這一步,正好對(duì)應(yīng)2.4所講的。APP進(jìn)程存在的也會(huì)調(diào)用這個(gè)方法,而不存在則先創(chuàng)建進(jìn)程,最終也會(huì)執(zhí)行到這一步。

realStartActivityLocked中創(chuàng)建Activity的生命周期事務(wù),最終通過ClientLifecycleManager.scheduleTransaction通過binder發(fā)送到APP進(jìn)程的ApplicationThread.scheduleTransaction方法中,則AMS流程就完成了。

5.4?APP完成Activity的啟動(dòng)

生命周期事務(wù)是安卓8.0之后出現(xiàn)的,簡(jiǎn)單來說就是之前的模式是:

AMS發(fā)一個(gè)協(xié)商好消息,APP收到后,根據(jù)消息內(nèi)存來決定自己去做操作;

而事務(wù)模式下,AMS發(fā)送一系列事務(wù)到APP進(jìn)程,APP收到后,直接去執(zhí)行這一系列的事務(wù)。而這些事務(wù)就是activity的生命周期調(diào)用。文章來源地址http://www.zghlxwxcb.cn/news/detail-507886.html

到了這里,關(guān)于android源碼學(xué)習(xí)- APP啟動(dòng)流程(android12源碼)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【Android12】Monkey壓力測(cè)試源碼執(zhí)行流程分析

    【Android12】Monkey壓力測(cè)試源碼執(zhí)行流程分析

    Monkey是Android提供的用于應(yīng)用程序自動(dòng)化測(cè)試、壓力測(cè)試的測(cè)試工具。 其源碼路徑(Android12)位于 部署形式為Java Binary 通過Monkey,可以模擬用戶的Touch(單指、多指、手勢(shì))、按鍵(key)事件等,檢測(cè)應(yīng)用程序發(fā)生的ANR、Crash事件,并收集相關(guān)Debug信息等。 例如測(cè)試應(yīng)用com.packa

    2024年03月22日
    瀏覽(18)
  • Activity啟動(dòng)過程詳解(Android 12源碼分析)

    Activity啟動(dòng)過程詳解(Android 12源碼分析)

    啟動(dòng)一個(gè)Activity,通常有兩種情況,一種是在應(yīng)用內(nèi)部啟動(dòng)Activity,另一種是Launcher啟動(dòng) 1、應(yīng)用內(nèi)啟動(dòng) 通過startActivity來啟動(dòng)Activity 啟動(dòng)流程: 一、Activity啟動(dòng)的發(fā)起 二、Activity的管理——ATMS 三、線程切換即消息處理——mH 四、Activity啟動(dòng)核心實(shí)現(xiàn)——初始化及生命周期 2、

    2024年02月13日
    瀏覽(26)
  • Android S從桌面點(diǎn)擊圖標(biāo)啟動(dòng)APP流程 (六)

    系列文章 Android S從桌面點(diǎn)擊圖標(biāo)啟動(dòng)APP流程 (一) Android S從桌面點(diǎn)擊圖標(biāo)啟動(dòng)APP流程 (二) Android S從桌面點(diǎn)擊圖標(biāo)啟動(dòng)APP流程 (三) Android S從桌面點(diǎn)擊圖標(biāo)啟動(dòng)APP流程 (四) Android S從桌面點(diǎn)擊圖標(biāo)啟動(dòng)APP流程 (五) Android 12的源碼鏈接: android 12 aosp http://aospxref.com/android-12.0.0_r3/ 上文

    2024年02月06日
    瀏覽(28)
  • Android系統(tǒng)啟動(dòng)流程 源碼解析

    本文鏈接:https://blog.csdn.net/feather_wch/article/details/132518105 有道云腦圖:https://note.youdao.com/s/GZ9d8vzO 1、整體流程 Boot Room BootLoader idle kthread init init ServiceManager zygote zygote SystemServer app 1、kernel/common/init/main.c 2、andorid.mk-android.bp編譯 3、init是用戶空間鼻祖 屬于C、C++ Framework 1.1 啟動(dòng)源

    2024年02月11日
    瀏覽(30)
  • 【Android12】Android Framework系列---Adb和PMS安裝apk源碼流程

    【Android12】Android Framework系列---Adb和PMS安裝apk源碼流程

    通過adb install命令可以將apk安裝到Android系統(tǒng)(注意:特定類型的apk,比如persist類型是無法通過adb安裝的) 下述命令中adb解析install命令,并調(diào)用Android PackageManagerService進(jìn)行apk安裝。 基于Android12,分析從adb install到 PakcageManagerService安裝apk的流程。 adb install命令的源碼實(shí)現(xiàn) Andro

    2024年01月22日
    瀏覽(45)
  • Android 12 源碼分析 —— 應(yīng)用層 二(SystemUI大體組織和啟動(dòng)過程)

    Android 12 源碼分析 —— 應(yīng)用層 二(SystemUI大體組織和啟動(dòng)過程)

    在前一篇文章中,我們介紹了SystemUI怎么使用IDE進(jìn)行編輯和調(diào)試。這是分析SystemUI的最基礎(chǔ),希望讀者能盡量掌握。 本篇文章,將會(huì)介紹SystemUI的大概組織架構(gòu),以及它的啟動(dòng)過程。本篇文章讀完,將會(huì)知道: SystemUI為什么選擇使用Dagger2 SystemUI怎么新建一個(gè)模塊 SystemUI的啟動(dòng)

    2024年02月06日
    瀏覽(39)
  • 【Android】APP啟動(dòng)優(yōu)化學(xué)習(xí)筆記

    【Android】APP啟動(dòng)優(yōu)化學(xué)習(xí)筆記

    用戶體驗(yàn): 應(yīng)用的啟動(dòng)速度直接影響用戶體驗(yàn)。用戶希望應(yīng)用能夠快速啟動(dòng)并迅速響應(yīng)他們的操作。如果應(yīng)用啟動(dòng)較慢,用戶可能會(huì)感到不滿,并且有可能選擇卸載或切換到競(jìng)爭(zhēng)對(duì)手的應(yīng)用。通過啟動(dòng)優(yōu)化,可以提高應(yīng)用的啟動(dòng)速度,讓用戶獲得更好的使用體驗(yàn)。 競(jìng)爭(zhēng)優(yōu)勢(shì)

    2024年02月14日
    瀏覽(23)
  • Android 10.0 pms中關(guān)于啟動(dòng)app時(shí)獲取app的ActivityInfo信息相關(guān)源碼分析

    ?在android10.0的系統(tǒng)rom定制化開發(fā)中,在對(duì)于app啟動(dòng)時(shí),通過Launcher調(diào)用pms來查詢app的相關(guān)ActivityInfo的相關(guān)信息,然后調(diào)用 ams來啟動(dòng)activity,這篇來分析pms中獲取app的ActivityInfo的相關(guān)信息的相關(guān)源碼分析

    2024年02月02日
    瀏覽(28)
  • SpringBoot源碼學(xué)習(xí)4——SpringBoot內(nèi)嵌Tomcat啟動(dòng)流程源碼分析

    SpringBoot源碼學(xué)習(xí)4——SpringBoot內(nèi)嵌Tomcat啟動(dòng)流程源碼分析

    系列文章目錄和關(guān)于我 我在初學(xué)spring的時(shí)候,很懵逼,因?yàn)檎麄€(gè)項(xiàng)目中不存在main方法,讓我有點(diǎn)摸不著頭腦。那時(shí)候我知道有個(gè)東西叫tomcat是它監(jiān)聽了端口,解析了協(xié)議調(diào)到了我的servlet。 在我初學(xué)SpringBoot的時(shí)候,很懵逼,有main方法了,但是tomcat在哪里呢,又是如何啟動(dòng)起

    2024年02月04日
    瀏覽(20)
  • Android安卓實(shí)戰(zhàn)項(xiàng)目(12)—關(guān)于身體分析,BMI計(jì)算,喝水提醒,食物卡路里計(jì)算APP【支持中英文切換】生活助手類APP(源碼在文末)

    Android安卓實(shí)戰(zhàn)項(xiàng)目(12)—關(guān)于身體分析,BMI計(jì)算,喝水提醒,食物卡路里計(jì)算APP【支持中英文切換】生活助手類APP(源碼在文末)

    B站演示 【Android安卓實(shí)戰(zhàn)項(xiàng)目(12)—生活助手類APP—關(guān)于身體分析,BMI計(jì)算,喝水提醒,食物卡路里計(jì)算APP【支持中英文切換】】 https://www.bilibili.com/video/BV1Wu4y1C76j/?share_source=copy_webvd_source=b2e9b9ed746acda34f499009647748ed 這段代碼是一個(gè)Android應(yīng)用程序的主要活動(dòng)(Activity),它是一

    2024年02月10日
    瀏覽(25)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包