Android應(yīng)用啟動(dòng)流程之從啟動(dòng)到可交互的過(guò)程解析
一、導(dǎo)讀
我們繼續(xù)總結(jié)學(xué)習(xí)Android 基礎(chǔ)知識(shí),溫故知新。
還是在多年前做系統(tǒng)應(yīng)用開發(fā)的時(shí)候,通過(guò)編譯源碼學(xué)習(xí)了一遍APP的啟動(dòng)過(guò)程,
最近在整理應(yīng)用啟動(dòng)優(yōu)化相關(guān)的文檔,打算重新梳理一遍,并整理成一個(gè)通俗易懂的文檔,以備后面查看。
在學(xué)習(xí)過(guò)程中,大家最好是把源碼下載下來(lái)。
1.1 啟動(dòng)知識(shí)儲(chǔ)備
啟動(dòng)過(guò)程比較復(fù)雜,涉及到的知識(shí)點(diǎn)非常多,建議通過(guò)其他文章進(jìn)行學(xué)習(xí)。
1.2 Zygote進(jìn)程
Zygote進(jìn)程是Android設(shè)備啟動(dòng)時(shí)由init進(jìn)程創(chuàng)建和啟動(dòng),之后不斷接收來(lái)自應(yīng)用程序的請(qǐng)求。
Zygote進(jìn)程預(yù)先創(chuàng)建一個(gè)虛擬機(jī)和一些共享資源,以提高應(yīng)用程序的啟動(dòng)速度和系統(tǒng)資源的利用效率。
同時(shí),Zygote進(jìn)程也負(fù)責(zé)處理應(yīng)用程序進(jìn)程的環(huán)境初始化和加載核心類庫(kù)等操作。
每當(dāng)有新的應(yīng)用程序啟動(dòng)請(qǐng)求到達(dá)時(shí),Zygote進(jìn)程會(huì)fork出一個(gè)子進(jìn)程(應(yīng)用程序進(jìn)程)來(lái)運(yùn)行該應(yīng)用程序。
1.3 SystemServer進(jìn)程
SystemServer進(jìn)程是Android操作系統(tǒng)的一個(gè)關(guān)鍵進(jìn)程,它在設(shè)備啟動(dòng)時(shí)由init進(jìn)程創(chuàng)建的。
SystemServer進(jìn)程是一個(gè)守護(hù)進(jìn)程,在系統(tǒng)運(yùn)行期間一直存在,負(fù)責(zé)啟動(dòng)和管理各個(gè)核心系統(tǒng)服務(wù),如AMS、Window Manager、Package Manager等。
1.4 AMS(Activity Manager Service)
AMS(Activity Manager Service)是SystemServer進(jìn)程中的一個(gè)關(guān)鍵組件,負(fù)責(zé)管理所有應(yīng)用程序的生命周期和交互。它監(jiān)控應(yīng)用程序的啟動(dò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)程。每個(gè)運(yùn)行的應(yīng)用程序都會(huì)分配一個(gè)或多個(gè)獨(dú)立的APP進(jìn)程來(lái)承載應(yīng)用的執(zhí)行環(huán)境。
每個(gè)APP進(jìn)程都是Zygote進(jìn)程通過(guò)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)建和啟動(dòng)應(yīng)用程序的主Activity。
- 處理應(yīng)用程序的消息循環(huán),接收和分發(fā)來(lái)自系統(tǒng)和應(yīng)用程序的消息。
- 管理應(yīng)用程序的所有Activity的生命周期,包括創(chuàng)建、啟動(dòng)、暫停、恢復(fù)、停止和銷毀等。
- 處理應(yīng)用程序的資源加載和更新,包括布局文件、圖片、字符串等資源的加載。
- 處理應(yīng)用程序的窗口管理,包括窗口的創(chuàng)建、顯示、隱藏和更新等操作。
- 與AMS (Activity Manager Service)通信,處理Activity的啟動(dòng)、停止、切換等請(qǐng)求,并接收來(lái)自AMS的指令和請(qǐng)求。
- 處理應(yīng)用程序的異常錯(cuò)誤,包括崩潰、ANR (Application Not Responding)等情況的處理。
二、啟動(dòng)流程概覽
涉及到多個(gè)進(jìn)程之間的通信:
1、用戶點(diǎn)擊圖標(biāo)后,Laucher(手機(jī)桌面)會(huì)通過(guò)binder的方式通知SystemServer進(jìn)程。
2、SystemServer收到信息,內(nèi)部的AMS(Activity Manager Service)通知Zygote去創(chuàng)建APP進(jìn)程,通過(guò)反射調(diào)用ActivityThread.main方法,即創(chuàng)建主線程。
3、APP進(jìn)程創(chuàng)建后(Zygote進(jìn)行fork),通過(guò)回調(diào)通知AMS。
4、AMS收到信息后經(jīng)過(guò)一些列調(diào)用,通知APP進(jìn)程(ActivityThread)創(chuàng)建Application
5、Application 之后,繼續(xù)執(zhí)行調(diào)用到ClientLifecycleManager,進(jìn)行Activity創(chuàng)建等過(guò)程
我們畫個(gè)簡(jiǎn)單的圖


下面貼一下代碼:
2.1 用戶點(diǎn)擊桌面圖標(biāo)
Launcher獲取到AMS的binder,之后進(jìn)入到SystemServer進(jìn)程。
然后調(diào)用的zygote進(jìn)程,fork出一個(gè)新的app進(jìn)程。
2.2 創(chuàng)建app進(jìn)程
ActivityThread
應(yīng)用進(jìn)程啟動(dòng)的入口函數(shù)main()方法中,會(huì)調(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開啟無(wú)限循環(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綁定管理起來(lái)
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
}
. ..
}
. ..
}attachApplication 這個(gè)流程會(huì)分兩步:
1、創(chuàng)建應(yīng)用的application對(duì)象
2、activity啟動(dòng)顯示
2.3 創(chuàng)建 application
IActivityManager.aidl
void attachApplication(in IApplicationThread app, long startSeq);
ActivityManagerService
// 這里接受APP傳遞過(guò)來(lái)的消息
@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
synchronized (this) {
// 通過(guò) Binder 獲取 PID ,PID和UID都是進(jìn)程創(chuàng)建應(yīng)用的時(shí)候系統(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對(duì)象
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的啟動(dòng)頁(yè)面的方法,后面繼續(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, ...);
我們來(lái)看看 Application 是如何創(chuàng)建的
ActivityThread
由AMS調(diào)用過(guò)來(lái),具體看上面的代碼
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);
通過(guò) calssLoader 來(lái)創(chuàng)建 application 對(duì)象
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啟動(dòng)顯示
接著上面的代碼 mStackSupervisor.attachApplicationLocked(app);
ActivityStackSupervisor
方法realStartActivityLocked();
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
final String processName = app.processName;
boolean didSomething = false;
Activity啟動(dòng)的入口
try {
if (realStartActivityLocked(activity, app, top == activity, true)) {
}
} catch (RemoteException e) {
}
return didSomething;
}
真的開始啟動(dòng) 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
通過(guò)代碼,我們可以看到,獲取的client就是 ActivityThread,IApplicationThread是一個(gè)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中沒(méi)有復(fù)寫scheduleTransaction,會(huì)執(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)建并啟動(dò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實(shí)例化過(guò)程
/** Core implementation of activity launch. */
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
Activity activity = null;
try {
// 通過(guò)反射實(shí)例化Activity對(duì)象
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
} catch (Exception e) {
}
window
theme
//當(dāng)實(shí)例化Activity對(duì)象后,繼續(xù)執(zhí)行callActivityOnCreate
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
}接下來(lái)就是執(zhí)行 Activity 生命周期函數(shù)
所用的源碼不同,代碼可能會(huì)有些許差別。
以上就是Android應(yīng)用啟動(dòng)流程之從啟動(dòng)到可交互的過(guò)程解析的詳細(xì)內(nèi)容,更多關(guān)于Android應(yīng)用啟動(dòng)流程解析的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android中Splash應(yīng)用啟動(dòng)白屏問(wèn)題的解決方法
這篇文章主要為大家詳細(xì)介紹了Android中Splash應(yīng)用啟動(dòng)白屏問(wèn)題的兩種解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02
詳解Android原生json和fastjson的簡(jiǎn)單使用
本文主要介紹了Android原生json和fastjson的簡(jiǎn)單使用,具有一定的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-01-01
Android編程之計(jì)時(shí)器Chronometer簡(jiǎn)單示例
這篇文章主要介紹了Android計(jì)時(shí)器Chronometer簡(jiǎn)單用法,結(jié)合實(shí)例形式分析了Android計(jì)時(shí)器Chronometer的定義、事件響應(yīng)及界面布局相關(guān)操作技巧,需要的朋友可以參考下2017-08-08
Android 檢測(cè)鍵盤顯示或隱藏鍵盤的實(shí)現(xiàn)代碼
這篇文章主要介紹了Android 檢測(cè)鍵盤顯示或隱藏鍵盤的實(shí)現(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下2017-07-07
android文件操作——讀取assets和raw文件下的內(nèi)容
本篇文章主要介紹了android文件操作——讀取assets和raw文件下的內(nèi)容,并附簡(jiǎn)單實(shí)例代碼,需要的朋友可以參考下。2016-10-10
Android開發(fā)筆記 今天學(xué)到的一些屬性
離開實(shí)驗(yàn)室之前再貼上今天下午自己學(xué)到的一些基礎(chǔ)知識(shí) 上午干嘛了呢,忙著數(shù)據(jù)恢復(fù)呢2012-11-11

