摘要:孵化進程相當于是系統的根進程,后面所有的進程都是通過這個進程出來的雖然進程相當于系統的根進程,但是事實上它也是由系統的進程啟動的。
目錄介紹
1.什么是Zygote進程
1.1 簡單介紹
1.2 各個進程的先后順序
1.3 進程作用說明
2.Zygote進程的啟動流程
2.1 源碼位置
2.2 ZygoteInit類的main方法
2.3 registerZygoteSocket(socketName)分析
2.4 preLoad()方法分析
2.5 startSystemServer()啟動進程
3.SystemServer進程啟動流程
3.1 SystemServer進程簡介
3.2 SystemServer的main方法
3.3 查看run方法
3.4 run方法中createSystemContext()解析
3.5 mSystemServiceManager的創建
4.啟動服務
4.1 啟動哪些服務
4.2 啟動服務流程源碼分析
4.3 啟動部分服務
好消息博客筆記大匯總【16年3月到至今】,包括Java基礎及深入知識點,Android技術博客,Python學習筆記等等,還包括平時開發中遇到的bug匯總,當然也在工作之余收集了大量的面試題,長期更新維護并且修正,持續完善……開源的文件是markdown格式的!同時也開源了生活博客,從12年起,積累共計47篇[近20萬字],轉載請注明出處,謝謝!
鏈接地址:https://github.com/yangchong2...
如果覺得好,可以star一下,謝謝!當然也歡迎提出建議,萬事起于忽微,量變引起質變!
1.什么是Zygote進程 1.1 簡單介紹Zygote進程是所有的android進程的父進程,包括SystemServer和各種應用進程都是通過Zygote進程fork出來的。Zygote(孵化)進程相當于是android系統的根進程,后面所有的進程都是通過這個進程fork出來的
雖然Zygote進程相當于Android系統的根進程,但是事實上它也是由Linux系統的init進程啟動的。
1.2 各個進程的先后順序init進程 --> Zygote進程 --> SystemServer進程 -->各種應用進程
1.3 進程作用說明init進程:linux的根進程,android系統是基于linux系統的,因此可以算作是整個android操作系統的第一個進程;
Zygote進程:android系統的根進程,主要作用:可以作用Zygote進程fork出SystemServer進程和各種應用進程;
SystemService進程:主要是在這個進程中啟動系統的各項服務,比如ActivityManagerService,PackageManagerService,WindowManagerService服務等等;
各種應用進程:啟動自己編寫的客戶端應用時,一般都是重新啟動一個應用進程,有自己的虛擬機與運行環境;
2.Zygote進程的啟動流程 2.1 源碼位置位置:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
Zygote進程mian方法主要執行邏輯:
初始化DDMS;
注冊Zygote進程的socket通訊;
初始化Zygote中的各種類,資源文件,OpenGL,類庫,Text資源等等;
初始化完成之后fork出SystemServer進程;
fork出SystemServer進程之后,關閉socket連接;
2.2 ZygoteInit類的main方法
init進程在啟動Zygote進程時一般都會調用ZygoteInit類的main方法,因此這里看一下該方法的具體實現(基于android23源碼);
調用enableDdms(),設置DDMS可用,可以發現DDMS啟動的時機還是比較早的,在整個Zygote進程剛剛開始要啟動額時候就設置可用。
之后初始化各種參數
通過調用registerZygoteSocket方法,注冊為Zygote進程注冊Socket
然后調用preload方法實現預加載各種資源
然后通過調用startSystemServer開啟SystemServer服務,這個是重點
public static void main(String argv[]) { try { //設置ddms可以用 RuntimeInit.enableDdms(); SamplingProfilerIntegration.start(); boolean startSystemServer = false; String socketName = "zygote"; String abiList = null; for (int i = 1; i < argv.length; i++) { if ("start-system-server".equals(argv[i])) { startSystemServer = true; } else if (argv[i].startsWith(ABI_LIST_ARG)) { abiList = argv[i].substring(ABI_LIST_ARG.length()); } else if (argv[i].startsWith(SOCKET_NAME_ARG)) { socketName = argv[i].substring(SOCKET_NAME_ARG.length()); } else { throw new RuntimeException("Unknown command line argument: " + argv[i]); } } if (abiList == null) { throw new RuntimeException("No ABI list supplied."); } registerZygoteSocket(socketName); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis()); preload(); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, SystemClock.uptimeMillis()); SamplingProfilerIntegration.writeZygoteSnapshot(); gcAndFinalize(); Trace.setTracingEnabled(false); if (startSystemServer) { startSystemServer(abiList, socketName); } Log.i(TAG, "Accepting command socket connections"); runSelectLoop(abiList); closeServerSocket(); } catch (MethodAndArgsCaller caller) { caller.run(); } catch (RuntimeException ex) { Log.e(TAG, "Zygote died with exception", ex); closeServerSocket(); throw ex; } }2.3 registerZygoteSocket(socketName)分析
調用registerZygoteSocket(String socketName)為Zygote進程注冊socket
private static void registerZygoteSocket(String socketName) { if (sServerSocket == null) { int fileDesc; final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName; try { String env = System.getenv(fullSocketName); fileDesc = Integer.parseInt(env); } catch (RuntimeException ex) { throw new RuntimeException(fullSocketName + " unset or invalid", ex); } try { FileDescriptor fd = new FileDescriptor(); fd.setInt$(fileDesc); sServerSocket = new LocalServerSocket(fd); } catch (IOException ex) { throw new RuntimeException( "Error binding to local socket "" + fileDesc + """, ex); } } }2.4 preLoad()方法分析
源碼如下所示
static void preload() { Log.d(TAG, "begin preload"); preloadClasses(); preloadResources(); preloadOpenGL(); preloadSharedLibraries(); preloadTextResources(); // Ask the WebViewFactory to do any initialization that must run in the zygote process, // for memory sharing purposes. WebViewFactory.prepareWebViewInZygote(); Log.d(TAG, "end preload"); }
大概操作是這樣的:
preloadClasses()用于初始化Zygote中需要的class類;
preloadResources()用于初始化系統資源;
preloadOpenGL()用于初始化OpenGL;
preloadSharedLibraries()用于初始化系統libraries;
preloadTextResources()用于初始化文字資源;
prepareWebViewInZygote()用于初始化webview;
2.5 startSystemServer()啟動進程
這段邏輯的執行邏輯就是通過Zygote fork出SystemServer進程
private static boolean startSystemServer(String abiList, String socketName) throws MethodAndArgsCaller, RuntimeException { long capabilities = posixCapabilitiesAsBits( OsConstants.CAP_BLOCK_SUSPEND, OsConstants.CAP_KILL, OsConstants.CAP_NET_ADMIN, OsConstants.CAP_NET_BIND_SERVICE, OsConstants.CAP_NET_BROADCAST, OsConstants.CAP_NET_RAW, OsConstants.CAP_SYS_MODULE, OsConstants.CAP_SYS_NICE, OsConstants.CAP_SYS_RESOURCE, OsConstants.CAP_SYS_TIME, OsConstants.CAP_SYS_TTY_CONFIG ); /* Hardcoded command line to start the system server */ String args[] = { "--setuid=1000", "--setgid=1000", "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007", "--capabilities=" + capabilities + "," + capabilities, "--nice-name=system_server", "--runtime-args", "com.android.server.SystemServer", }; ZygoteConnection.Arguments parsedArgs = null; int pid; try { parsedArgs = new ZygoteConnection.Arguments(args); ZygoteConnection.applyDebuggerSystemProperty(parsedArgs); ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs); /* Request to fork the system server process */ pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } /* For child process */ if (pid == 0) { if (hasSecondZygote(abiList)) { waitForSecondaryZygote(socketName); } handleSystemServerProcess(parsedArgs); } return true; }3.SystemServer進程啟動流程 3.1 SystemServer進程簡介
SystemServer進程主要的作用是在這個進程中啟動各種系統服務,比如ActivityManagerService,PackageManagerService,WindowManagerService服務,以及各種系統性的服務其實都是在SystemServer進程中啟動的,而當我們的應用需要使用各種系統服務的時候其實也是通過與SystemServer進程通訊獲取各種服務對象的句柄的。
3.2 SystemServer的main方法如下所示,比較簡單,只是new出一個SystemServer對象并執行其run方法,查看SystemServer類的定義我們知道其實final類型的,所以我們一般不能重寫或者繼承。
3.3 查看run方法
代碼如下所示
首先判斷系統當前時間,若當前時間小于1970年1月1日,則一些初始化操作可能會處所,所以當系統的當前時間小于1970年1月1日的時候,設置系統當前時間為該時間點。
然后是設置系統的語言環境等
接著設置虛擬機運行內存,加載運行庫,設置SystemServer的異步消息
private void run() { if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) { Slog.w(TAG, "System clock is before 1970; setting to 1970."); SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME); } if (!SystemProperties.get("persist.sys.language").isEmpty()) { final String languageTag = Locale.getDefault().toLanguageTag(); SystemProperties.set("persist.sys.locale", languageTag); SystemProperties.set("persist.sys.language", ""); SystemProperties.set("persist.sys.country", ""); SystemProperties.set("persist.sys.localevar", ""); } Slog.i(TAG, "Entered the Android system server!"); EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis()); SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary()); if (SamplingProfilerIntegration.isEnabled()) { SamplingProfilerIntegration.start(); mProfilerSnapshotTimer = new Timer(); mProfilerSnapshotTimer.schedule(new TimerTask() { @Override public void run() { SamplingProfilerIntegration.writeSnapshot("system_server", null); } }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL); } // Mmmmmm... more memory! VMRuntime.getRuntime().clearGrowthLimit(); // The system server has to run all of the time, so it needs to be // as efficient as possible with its memory usage. VMRuntime.getRuntime().setTargetHeapUtilization(0.8f); // Some devices rely on runtime fingerprint generation, so make sure // we"ve defined it before booting further. Build.ensureFingerprintProperty(); // Within the system server, it is an error to access Environment paths without // explicitly specifying a user. Environment.setUserRequired(true); // Ensure binder calls into the system always run at foreground priority. BinderInternal.disableBackgroundScheduling(true); // Prepare the main looper thread (this thread). android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_FOREGROUND); android.os.Process.setCanSelfBackground(false); Looper.prepareMainLooper(); // Initialize native services. System.loadLibrary("android_servers"); // Check whether we failed to shut down last time we tried. // This call may not return. performPendingShutdown(); // Initialize the system context. createSystemContext(); // Create the system service manager. mSystemServiceManager = new SystemServiceManager(mSystemContext); LocalServices.addService(SystemServiceManager.class, mSystemServiceManager); // Start services. try { startBootstrapServices(); startCoreServices(); startOtherServices(); } catch (Throwable ex) { Slog.e("System", "******************************************"); Slog.e("System", "************ Failure starting system services", ex); throw ex; } // For debug builds, log event loop stalls to dropbox for analysis. if (StrictMode.conditionallyEnableDebugLogging()) { Slog.i(TAG, "Enabled StrictMode for system server main thread."); } // Loop forever. Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }
然后下面的代碼是:
// Initialize the system context. createSystemContext(); // Create the system service manager. mSystemServiceManager = new SystemServiceManager(mSystemContext); LocalServices.addService(SystemServiceManager.class, mSystemServiceManager); // Start services. try { startBootstrapServices(); startCoreServices(); startOtherServices(); } catch (Throwable ex) { Slog.e("System", "******************************************"); Slog.e("System", "************ Failure starting system services", ex); throw ex; }3.4 run方法中createSystemContext()解析
調用createSystemContext()方法:
可以看到在SystemServer進程中也存在著Context對象,并且是通過ActivityThread.systemMain方法創建context的,這一部分的邏輯以后會通過介紹Activity的啟動流程來介紹,這里就不在擴展,只知道在SystemServer進程中也需要創建Context對象。
private void createSystemContext() { ActivityThread activityThread = ActivityThread.systemMain(); mSystemContext = activityThread.getSystemContext(); mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar); }3.5 mSystemServiceManager的創建
看run方法中,通過SystemServiceManager的構造方法創建了一個新的SystemServiceManager對象,我們知道SystemServer進程主要是用來構建系統各種service服務的,而SystemServiceManager就是這些服務的管理對象。
然后調用:
將SystemServiceManager對象保存SystemServer進程中的一個數據結構中。
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
最后開始執行:
// Start services. try { startBootstrapServices(); startCoreServices(); startOtherServices(); } catch (Throwable ex) { Slog.e("System", "******************************************"); Slog.e("System", "************ Failure starting system services", ex); throw ex; }
里面主要涉及了是三個方法:
startBootstrapServices() 主要用于啟動系統Boot級服務
startCoreServices() 主要用于啟動系統核心的服務
startOtherServices() 主要用于啟動一些非緊要或者是非需要及時啟動的服務
4.啟動服務 4.1 啟動哪些服務在開始執行啟動服務之前總是會先嘗試通過socket方式連接Zygote進程,在成功連接之后才會開始啟動其他服務。
4.2 啟動服務流程源碼分析
首先看一下startBootstrapServices方法:
private void startBootstrapServices() { Installer installer = mSystemServiceManager.startService(Installer.class); mActivityManagerService = mSystemServiceManager.startService( ActivityManagerService.Lifecycle.class).getService(); mActivityManagerService.setSystemServiceManager(mSystemServiceManager); mActivityManagerService.setInstaller(installer); mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class); mActivityManagerService.initPowerManagement(); // Manages LEDs and display backlight so we need it to bring up the display. mSystemServiceManager.startService(LightsService.class); // Display manager is needed to provide display metrics before package manager // starts up. mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class); // We need the default display before we can initialize the package manager. mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY); // Only run "core" apps if we"re encrypting the device. String cryptState = SystemProperties.get("vold.decrypt"); if (ENCRYPTING_STATE.equals(cryptState)) { Slog.w(TAG, "Detected encryption in progress - only parsing core apps"); mOnlyCore = true; } else if (ENCRYPTED_STATE.equals(cryptState)) { Slog.w(TAG, "Device encrypted - only parsing core apps"); mOnlyCore = true; } // Start the package manager. Slog.i(TAG, "Package Manager"); mPackageManagerService = PackageManagerService.main(mSystemContext, installer, mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore); mFirstBoot = mPackageManagerService.isFirstBoot(); mPackageManager = mSystemContext.getPackageManager(); Slog.i(TAG, "User Service"); ServiceManager.addService(Context.USER_SERVICE, UserManagerService.getInstance()); // Initialize attribute cache used to cache resources from packages. AttributeCache.init(mSystemContext); // Set up the Application instance for the system process and get started. mActivityManagerService.setSystemProcess(); // The sensor service needs access to package manager service, app ops // service, and permissions service, therefore we start it after them. startSensorService(); }
先執行:
Installer installer = mSystemServiceManager.startService(Installer.class);
mSystemServiceManager是系統服務管理對象,在main方法中已經創建完成,這里我們看一下其startService方法的具體實現:
可以看到通過反射器構造方法創建出服務類,然后添加到SystemServiceManager的服務列表數據中,最后調用了service.onStart()方法,因為傳遞的是Installer.class
publicT startService(Class serviceClass) { final String name = serviceClass.getName(); Slog.i(TAG, "Starting " + name); // Create the service. if (!SystemService.class.isAssignableFrom(serviceClass)) { throw new RuntimeException("Failed to create " + name + ": service must extend " + SystemService.class.getName()); } final T service; try { Constructor constructor = serviceClass.getConstructor(Context.class); service = constructor.newInstance(mContext); } catch (InstantiationException ex) { throw new RuntimeException("Failed to create service " + name + ": service could not be instantiated", ex); } catch (IllegalAccessException ex) { throw new RuntimeException("Failed to create service " + name + ": service must have a public constructor with a Context argument", ex); } catch (NoSuchMethodException ex) { throw new RuntimeException("Failed to create service " + name + ": service must have a public constructor with a Context argument", ex); } catch (InvocationTargetException ex) { throw new RuntimeException("Failed to create service " + name + ": service constructor threw an exception", ex); } // Register it. mServices.add(service); // Start it. try { service.onStart(); } catch (RuntimeException ex) { throw new RuntimeException("Failed to start service " + name + ": onStart threw an exception", ex); } return service; }
看一下Installer的onStart方法:
很簡單就是執行了mInstaller的waitForConnection方法,這里簡單介紹一下Installer類,該類是系統安裝apk時的一個服務類,繼承SystemService(系統服務的一個抽象接口),需要在啟動完成Installer服務之后才能啟動其他的系統服務。
@Override public void onStart() { Slog.i(TAG, "Waiting for installd to be ready."); mInstaller.waitForConnection(); }
然后查看waitForConnection()方法:
通過追蹤代碼可以發現,其在不斷的通過ping命令連接Zygote進程(SystemServer和Zygote進程通過socket方式通訊,其他進程通過Binder方式通訊)
public void waitForConnection() { for (;;) { if (execute("ping") >= 0) { return; } Slog.w(TAG, "installd not ready"); SystemClock.sleep(1000); } }
繼續看startBootstrapServices方法:
這段代碼主要是用于啟動ActivityManagerService服務,并為其設置SysServiceManager和Installer。ActivityManagerService是系統中一個非常重要的服務,Activity,service,Broadcast,contentProvider都需要通過其余系統交互。
// Activity manager runs the show. mActivityManagerService = mSystemServiceManager.startService( ActivityManagerService.Lifecycle.class).getService(); mActivityManagerService.setSystemServiceManager(mSystemServiceManager); mActivityManagerService.setInstaller(installer);
首先看一下Lifecycle類的定義:
可以看到其實ActivityManagerService的一個靜態內部類,在其構造方法中會創建一個ActivityManagerService,通過剛剛對Installer服務的分析我們知道,SystemServiceManager的startService方法會調用服務的onStart()方法,而在Lifecycle類的定義中我們看到其onStart()方法直接調用了mService.start()方法,mService是Lifecycle類中對ActivityManagerService的引用
public static final class Lifecycle extends SystemService { private final ActivityManagerService mService; public Lifecycle(Context context) { super(context); mService = new ActivityManagerService(context); } @Override public void onStart() { mService.start(); } public ActivityManagerService getService() { return mService; } }4.3 啟動部分服務
啟動PowerManagerService服務:
啟動方式跟上面的ActivityManagerService服務相似都會調用其構造方法和onStart方法,PowerManagerService主要用于計算系統中和Power相關的計算,然后決策系統應該如何反應。同時協調Power如何與系統其它模塊的交互,比如沒有用戶活動時,屏幕變暗等等。
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
然后是啟動LightsService服務
主要是手機中關于閃光燈,LED等相關的服務;也是會調用LightsService的構造方法和onStart方法;
mSystemServiceManager.startService(LightsService.class);
然后是啟動DisplayManagerService服務
主要是手機顯示方面的服務
mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
然后是啟動PackageManagerService,該服務也是android系統中一個比較重要的服務
包括多apk文件的安裝,解析,刪除,卸載等等操作。
可以看到PackageManagerService服務的啟動方式與其他服務的啟動方式有一些區別,直接調用了PackageManagerService的靜態main方法
Slog.i(TAG, "Package Manager"); mPackageManagerService = PackageManagerService.main(mSystemContext, installer, mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore); mFirstBoot = mPackageManagerService.isFirstBoot(); mPackageManager = mSystemContext.getPackageManager();
看一下其main方法的具體實現:
可以看到也是直接使用new的方式創建了一個PackageManagerService對象,并在其構造方法中初始化相關變量,最后調用了ServiceManager.addService方法,主要是通過Binder機制與JNI層交互
public static PackageManagerService main(Context context, Installer installer, boolean factoryTest, boolean onlyCore) { PackageManagerService m = new PackageManagerService(context, installer, factoryTest, onlyCore); ServiceManager.addService("package", m); return m; }
然后查看startCoreServices方法:
可以看到這里啟動了BatteryService(電池相關服務),UsageStatsService,WebViewUpdateService服務等。
private void startCoreServices() { // Tracks the battery level. Requires LightService. mSystemServiceManager.startService(BatteryService.class); // Tracks application usage stats. mSystemServiceManager.startService(UsageStatsService.class); mActivityManagerService.setUsageStatsManager( LocalServices.getService(UsageStatsManagerInternal.class)); // Update after UsageStatsService is available, needed before performBootDexOpt. mPackageManagerService.getUsageStatsIfNoPackageUsageInfo(); // Tracks whether the updatable WebView is in a ready state and watches for update installs. mSystemServiceManager.startService(WebViewUpdateService.class); }總結:
SystemServer進程是android中一個很重要的進程由Zygote進程啟動;
SystemServer進程主要用于啟動系統中的服務;
SystemServer進程啟動服務的啟動函數為main函數;
SystemServer在執行過程中首先會初始化一些系統變量,加載類庫,創建Context對象,創建SystemServiceManager對象等之后才開始啟動系統服務;
SystemServer進程將系統服務分為三類:boot服務,core服務和other服務,并逐步啟動
SertemServer進程在嘗試啟動服務之前會首先嘗試與Zygote建立socket通訊,只有通訊成功之后才會開始嘗試啟動服務;
創建的系統服務過程中主要通過SystemServiceManager對象來管理,通過調用服務對象的構造方法和onStart方法初始化服務的相關變量;
服務對象都有自己的異步消息對象,并運行在多帶帶的線程中;
參考博客https://www.jianshu.com/p/064...
http://blog.csdn.net/qq_23547...
http://www.xuebuyuan.com/2178...
https://www.jianshu.com/p/e69...
http://blog.csdn.net/luosheng...
http://blog.csdn.net/ericming...
關于其他內容介紹 01.關于博客匯總鏈接1.技術博客匯總
2.開源項目匯總
3.生活博客匯總
4.喜馬拉雅音頻匯總
5.其他匯總
02.關于我的博客我的個人站點:www.yczbj.org,www.ycbjie.cn
github:https://github.com/yangchong211
知乎:https://www.zhihu.com/people/...
簡書:http://www.jianshu.com/u/b7b2...
csdn:http://my.csdn.net/m0_37700275
喜馬拉雅聽書:http://www.ximalaya.com/zhubo...
開源中國:https://my.oschina.net/zbj161...
泡在網上的日子:http://www.jcodecraeer.com/me...
郵箱:yangchong211@163.com
阿里云博客:https://yq.aliyun.com/users/a... 239.headeruserinfo.3.dT4bcV
segmentfault頭條:https://segmentfault.com/u/xi...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/72062.html
摘要:馬蜂窩旅游歷經幾十個版本的開發迭代,在啟動流程上積累了一定的技術債務。我們定義啟動廣告曝光率啟動廣告曝光啟動廣告加載。 增長、活躍、留存是移動 App 的常見核心指標,直接反映一款 App 甚至一個互聯網公司運行的健康程度和發展動能。啟動流程的體驗決定了用戶的第一印象,在一定程度上影響了用戶活躍度和留存率。因此,確保啟動流程的良好體驗至關重要。 「馬蜂窩旅游」App 是馬蜂窩為用戶提供...
摘要:啟動流程主要的啟動流程就是下面的步引入包實例化編寫中間件監聽服務器引入包引入包其實就是引入的一個繼承于原生的類的類其中就包含了等原型方法實例化執行,將等對象封裝在實例中編寫中間件首先判斷的類型,不是方法直接拋錯是生成器函數的話用封裝是函數 啟動流程 koa 主要的啟動流程就是下面的 4 步:引入 koa 包 => 實例化 koa => 編寫中間件 => 監聽服務器 const koa ...
摘要:年月日階段劃分請求到響應的整個執行階段歸納為個程序啟動準備階段文件自動加載服務容器實例化基礎服務提供者的注冊核心類的實例化請求實例化階段實例化實例請求處理階段準備請求處理的環境將請求實例通過中間件處理及通過路由和控制器的分發控制響應發送和 Last-Modified: 2019年5月10日16:19:07 階段劃分 Laravel 5.5請求到響應的整個執行階段歸納為 4 個: ...
閱讀 3716·2021-11-23 09:51
閱讀 1378·2021-11-10 14:35
閱讀 4016·2021-09-22 15:01
閱讀 1289·2021-08-19 11:12
閱讀 386·2019-08-30 15:53
閱讀 1696·2019-08-29 13:04
閱讀 3435·2019-08-29 12:52
閱讀 3063·2019-08-23 16:14