Android應(yīng)用啟動流程之從啟動到可交互的過程解析
一、導(dǎo)讀
我們繼續(xù)總結(jié)學(xué)習(xí)Android 基礎(chǔ)知識,溫故知新。
還是在多年前做系統(tǒng)應(yīng)用開發(fā)的時候,通過編譯源碼學(xué)習(xí)了一遍APP的啟動過程,
最近在整理應(yīng)用啟動優(yōu)化相關(guān)的文檔,打算重新梳理一遍,并整理成一個通俗易懂的文檔,以備后面查看。
在學(xué)習(xí)過程中,大家最好是把源碼下載下來。
1.1 啟動知識儲備
啟動過程比較復(fù)雜,涉及到的知識點非常多,建議通過其他文章進(jìn)行學(xué)習(xí)。
1.2 Zygote進(jìn)程
Zygote進(jìn)程是Android設(shè)備啟動時由init進(jìn)程創(chuàng)建和啟動,之后不斷接收來自應(yīng)用程序的請求。
Zygote進(jìn)程預(yù)先創(chuàng)建一個虛擬機(jī)和一些共享資源,以提高應(yīng)用程序的啟動速度和系統(tǒng)資源的利用效率。
同時,Zygote進(jìn)程也負(fù)責(zé)處理應(yīng)用程序進(jìn)程的環(huán)境初始化和加載核心類庫等操作。
每當(dāng)有新的應(yīng)用程序啟動請求到達(dá)時,Zygote進(jìn)程會fork出一個子進(jìn)程(應(yīng)用程序進(jìn)程)來運(yùn)行該應(yīng)用程序。
1.3 SystemServer進(jìn)程
SystemServer進(jìn)程是Android操作系統(tǒng)的一個關(guān)鍵進(jìn)程,它在設(shè)備啟動時由init進(jìn)程創(chuàng)建的。
SystemServer進(jìn)程是一個守護(hù)進(jìn)程,在系統(tǒng)運(yùn)行期間一直存在,負(fù)責(zé)啟動和管理各個核心系統(tǒng)服務(wù),如AMS、Window Manager、Package Manager等。
1.4 AMS(Activity Manager Service)
AMS(Activity Manager Service)是SystemServer進(jìn)程中的一個關(guān)鍵組件,負(fù)責(zé)管理所有應(yīng)用程序的生命周期和交互。它監(jiān)控應(yīng)用程序的啟動、暫停、恢復(fù)和銷毀,
并協(xié)調(diào)應(yīng)用程序之間的切換和交互。除此之外,AMS還處理任務(wù)棧管理、權(quán)限管理、用戶通知等相關(guān)任務(wù)。
1.5 APP進(jìn)程(ActivityThread)
APP進(jìn)程是指在Android系統(tǒng)中運(yùn)行的應(yīng)用程序進(jìn)程。每個運(yùn)行的應(yīng)用程序都會分配一個或多個獨立的APP進(jìn)程來承載應(yīng)用的執(zhí)行環(huán)境。
每個APP進(jìn)程都是Zygote進(jìn)程通過fork系統(tǒng)調(diào)用創(chuàng)建的子進(jìn)程。
ActivityThread 是Android應(yīng)用程序的主線程,負(fù)責(zé)管理和調(diào)度應(yīng)用程序中的所有Activity的生命周期以及處理一些系統(tǒng)事件。
ActivityThread的主要職責(zé)包括:
- 創(chuàng)建和啟動應(yīng)用程序的主Activity。
- 處理應(yīng)用程序的消息循環(huán),接收和分發(fā)來自系統(tǒng)和應(yīng)用程序的消息。
- 管理應(yīng)用程序的所有Activity的生命周期,包括創(chuàng)建、啟動、暫停、恢復(fù)、停止和銷毀等。
- 處理應(yīng)用程序的資源加載和更新,包括布局文件、圖片、字符串等資源的加載。
- 處理應(yīng)用程序的窗口管理,包括窗口的創(chuàng)建、顯示、隱藏和更新等操作。
- 與AMS (Activity Manager Service)通信,處理Activity的啟動、停止、切換等請求,并接收來自AMS的指令和請求。
- 處理應(yīng)用程序的異常錯誤,包括崩潰、ANR (Application Not Responding)等情況的處理。
二、啟動流程概覽
涉及到多個進(jìn)程之間的通信:
1、用戶點擊圖標(biāo)后,Laucher(手機(jī)桌面)會通過binder的方式通知SystemServer進(jìn)程。
2、SystemServer收到信息,內(nèi)部的AMS(Activity Manager Service)通知Zygote去創(chuàng)建APP進(jìn)程,通過反射調(diào)用ActivityThread.main方法,即創(chuàng)建主線程。
3、APP進(jìn)程創(chuàng)建后(Zygote進(jìn)行fork),通過回調(diào)通知AMS。
4、AMS收到信息后經(jīng)過一些列調(diào)用,通知APP進(jìn)程(ActivityThread)創(chuàng)建Application
5、Application 之后,繼續(xù)執(zhí)行調(diào)用到ClientLifecycleManager,進(jìn)行Activity創(chuàng)建等過程
我們畫個簡單的圖
下面貼一下代碼:
2.1 用戶點擊桌面圖標(biāo)
Launcher獲取到AMS的binder,之后進(jìn)入到SystemServer進(jìn)程。
然后調(diào)用的zygote進(jìn)程,fork出一個新的app進(jìn)程。
2.2 創(chuàng)建app進(jìn)程
ActivityThread
應(yīng)用進(jìn)程啟動的入口函數(shù)main()方法中,會調(diào)用Looper相關(guān)的初始化和循環(huán)方法,從而讓主線程的Looper進(jìn)入循環(huán)狀態(tài),保證app進(jìn)程的一直運(yùn)行狀態(tài) public static void main(String[] args) { . .. //looper綁定主線程 Looper.prepareMainLooper(); 創(chuàng)建ActivityThread ActivityThread thread = new ActivityThread(); thread.attach(false, startSeq); //looper開啟無限循環(huán)讀取消息 Looper.loop(); . .. } private void attach(boolean system, long startSeq) { if (!system) { . .. final IActivityManager mgr = ActivityManager.getService(); try { // 通知 AMS, 并將當(dāng)前進(jìn)程的binder句柄傳給AMS綁定管理起來 mgr.attachApplication(mAppThread, startSeq); } catch (RemoteException ex) { } . .. } . .. }
attachApplication 這個流程會分兩步:
1、創(chuàng)建應(yīng)用的application對象
2、activity啟動顯示
2.3 創(chuàng)建 application
IActivityManager.aidl
void attachApplication(in IApplicationThread app, long startSeq);
ActivityManagerService
// 這里接受APP傳遞過來的消息 @Override public final void attachApplication(IApplicationThread thread, long startSeq) { synchronized (this) { // 通過 Binder 獲取 PID ,PID和UID都是進(jìn)程創(chuàng)建應(yīng)用的時候系統(tǒng)指定的 int callingPid = Binder.getCallingPid(); final int callingUid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); attachApplicationLocked(thread, callingPid, callingUid, startSeq); } } @GuardedBy("this") private final boolean attachApplicationLocked(IApplicationThread thread, int pid, int callingUid, long startSeq) { // *** 1、通知APP進(jìn)程進(jìn)行初始化操作,初始化application,創(chuàng)建應(yīng)用進(jìn)程的application對象 if (app.isolatedEntryPoint != null) { } else if (app.instr != null) { thread.bindApplication(processName, appInfo, providers, ...); } else { thread.bindApplication(processName, appInfo, providers, ...); } // *** 2、 通知APP拉起指定的MainActivity,調(diào)用ATMS的啟動頁面的方法,后面繼續(xù)介紹 // See if the top visible activity is waiting to run in this process... if (normalMode) { try { if (mStackSupervisor.attachApplicationLocked(app)) { didSomething = true; } } catch (Exception e) { } } }
IApplicationThread.aidl
void bindApplication(in String packageName, in ApplicationInfo info, ...);
我們來看看 Application 是如何創(chuàng)建的
ActivityThread
由AMS調(diào)用過來,具體看上面的代碼 public final void bindApplication(String processName, ApplicationInfo appInfo, ...) { sendMessage(H.BIND_APPLICATION, data); } public void handleMessage(Message msg) { switch (msg.what) { case BIND_APPLICATION: AppBindData data = (AppBindData)msg.obj; handleBindApplication(data); break; . .. } } private void handleBindApplication(AppBindData data) { Application app; try{ classLoader加載APK中的dex,并且加載APK的資源 final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo, appContext.getClassLoader(), false, true, false); final ContextImpl instrContext = ContextImpl.createAppContext(this, pi); 通過 calssLoader 來創(chuàng)建 application 對象 app=data.info.makeApplication(data.restrictedBackupMode,null); try{ 調(diào)用Application的onCreate mInstrumentation.onCreate(data.instrumentationArgs); }catch(Exception e){ } try{ mInstrumentation.callApplicationOnCreate(app); }catch(Exception e){ } } ... } public Application newApplication(ClassLoader cl, String className, Context context) 。。{ Application app = getFactory(context.getPackageName()).instantiateApplication(cl, className); app.attach(context); return app; } (Application) cl.loadClass(className).newInstance();
2.4 activity啟動顯示
接著上面的代碼 mStackSupervisor.attachApplicationLocked(app);
ActivityStackSupervisor
方法realStartActivityLocked();
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException { final String processName = app.processName; boolean didSomething = false; Activity啟動的入口 try { if (realStartActivityLocked(activity, app, top == activity, true)) { } } catch (RemoteException e) { } return didSomething; } 真的開始啟動 activity final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException { // Create activity launch transaction. final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread, r.appToken); clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent), System.identityHashCode(r), r.info, // TODO: Have this take the merged configuration instead of separate global // and override configs. mergedConfiguration.getGlobalConfiguration(), mergedConfiguration.getOverrideConfiguration(), r.compat, r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results, newIntents, mService.isNextTransitionForward(), profilerInfo)); // Schedule transaction. mService.getLifecycleManager().scheduleTransaction(clientTransaction); }
ActivityManagerService
ClientLifecycleManager getLifecycleManager() { return mLifecycleManager; }
ClientLifecycleManager
通過代碼,我們可以看到,獲取的client就是 ActivityThread,IApplicationThread是一個AIDL文件 void scheduleTransaction(ClientTransaction transaction) throws RemoteException { final IApplicationThread client = transaction.getClient(); transaction.schedule(); }
ClientTransaction
/** Target client. */ private IApplicationThread mClient; public void schedule() throws RemoteException { mClient.scheduleTransaction(this); }
ClientTransactionHandler
//ActivityThread中沒有復(fù)寫scheduleTransaction,會執(zhí)行到父類的方法 //public final class ActivityThread extends ClientTransactionHandler //ClientTransactionHandler.java public abstract class ClientTransactionHandler { void scheduleTransaction(ClientTransaction transaction) { transaction.preExecute(this); //發(fā)送消息 sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction); } }
ActivityThread.java
case EXECUTE_TRANSACTION: final ClientTransaction transaction = (ClientTransaction) msg.obj; mTransactionExecutor.execute(transaction); break;
繼續(xù)一系列調(diào)用
最后調(diào)用到ActivityThread,創(chuàng)建并啟動Activity
/** * Extended implementation of activity launch. Used when server requests a launch or relaunch. */ @Override public Activity handleLaunchActivity(ActivityClientRecord r, PendingTransactionActions pendingActions, Intent customIntent) { final Activity a = performLaunchActivity(r, customIntent); return a; } Activity實例化過程 /** Core implementation of activity launch. */ private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { Activity activity = null; try { // 通過反射實例化Activity對象 java.lang.ClassLoader cl = appContext.getClassLoader(); activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent); } catch (Exception e) { } window theme //當(dāng)實例化Activity對象后,繼續(xù)執(zhí)行callActivityOnCreate if (r.isPersistable()) { mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); } else { mInstrumentation.callActivityOnCreate(activity, r.state); } }
接下來就是執(zhí)行 Activity 生命周期函數(shù)
所用的源碼不同,代碼可能會有些許差別。
以上就是Android應(yīng)用啟動流程之從啟動到可交互的過程解析的詳細(xì)內(nèi)容,更多關(guān)于Android應(yīng)用啟動流程解析的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android中Splash應(yīng)用啟動白屏問題的解決方法
這篇文章主要為大家詳細(xì)介紹了Android中Splash應(yīng)用啟動白屏問題的兩種解決方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-02-02Android 檢測鍵盤顯示或隱藏鍵盤的實現(xiàn)代碼
這篇文章主要介紹了Android 檢測鍵盤顯示或隱藏鍵盤的實現(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下2017-07-07android文件操作——讀取assets和raw文件下的內(nèi)容
本篇文章主要介紹了android文件操作——讀取assets和raw文件下的內(nèi)容,并附簡單實例代碼,需要的朋友可以參考下。2016-10-10Android開發(fā)筆記 今天學(xué)到的一些屬性
離開實驗室之前再貼上今天下午自己學(xué)到的一些基礎(chǔ)知識 上午干嘛了呢,忙著數(shù)據(jù)恢復(fù)呢2012-11-11