Android?Activity啟動(dòng)流程刨析
前言
上篇文章寫(xiě)到 Service 的啟動(dòng)過(guò)程; 相對(duì)來(lái)說(shuō)Activity的啟動(dòng)過(guò)程比Service的啟動(dòng)過(guò)程更為復(fù)雜,其一Activity的生命周期方法比Service多,其二Activity具有啟動(dòng)模式和返回棧; 寫(xiě)本文的目的在于更清晰的梳理Activity的啟動(dòng)過(guò)程,加強(qiáng)自己的內(nèi)功修煉,力在以最簡(jiǎn)單的方式讓大家理解,跟大家一起學(xué)習(xí)
一、Binder的基本理解
Activity的啟動(dòng)有多次IPC過(guò)程,所以Binder屬于預(yù)備知識(shí),幫助我們更好理解系統(tǒng)的C/S的這種架構(gòu)模式
二、Activity啟動(dòng)的雙向IPC過(guò)程
一般Android各個(gè)應(yīng)用進(jìn)程的啟動(dòng)都以這樣一條路線,init進(jìn)程 –> Zygote進(jìn)程 –> SystemServer進(jìn)程 –>各種應(yīng)用進(jìn)程
- Init進(jìn)程:Linux的根進(jìn)程,Android系統(tǒng)是基于Linux系統(tǒng)的,因此可以算作是整個(gè)android操作系統(tǒng)的第一個(gè)進(jìn)程;
- Zygote進(jìn)程是所有應(yīng)用進(jìn)程的父進(jìn)程,所有的應(yīng)用進(jìn)程都是它孵化出來(lái)的;
- SystemServer進(jìn)程含有一些核心的服務(wù),比如ActivityManagerService,PackageManagerService,WindowManagerService等;
- 各種應(yīng)用進(jìn)程:?jiǎn)?dòng)自己編寫(xiě)的客戶端應(yīng)用時(shí),有自己的虛擬機(jī)與運(yùn)行環(huán)境。
由此可知應(yīng)用的第一個(gè)Activity的啟動(dòng)是多個(gè)進(jìn)程相互配合的結(jié)果,多個(gè)進(jìn)程相互配合就少不了使用Binder進(jìn)行IPC了,現(xiàn)在看一次IPC調(diào)用的過(guò)程是怎樣的。
上圖大概說(shuō)明了一次IPC的過(guò)程,或許你現(xiàn)在對(duì)里面各個(gè)類還不是很清楚,沒(méi)關(guān)系,大致了解一下
ActivityManagerService (下文簡(jiǎn)稱AMS),AMS是Android中最核心的服務(wù),實(shí)現(xiàn)了ActivityManager,主要負(fù)責(zé)系統(tǒng)中四大組件的啟動(dòng)、切換、調(diào)度及應(yīng)用進(jìn)程的管理和調(diào)度等工作,AMS提供了一個(gè)ArrayList mHistory來(lái)管理所有的Activity,Activity在AMS中的形式是ActivityRecord,Task在AMS中的形式為T(mén)askRecord,進(jìn)程在AMS中的管理形式為ProcessRecord,它在Android中特別重要
ActivityManagerNative (下文簡(jiǎn)稱AMN):由于AMS是系統(tǒng)核心服務(wù)在SystemServer進(jìn)程里面,很多API不能直接開(kāi)放供客戶端使用,所以需要通過(guò)IPC的方式,具體是這樣的,ActivityManager類內(nèi)部調(diào)用AMN的getDefault函數(shù)得到一個(gè)ActivityManagerProxy對(duì)象,通過(guò)它可與AMS通信
ActivityManagerProxy (下文簡(jiǎn)稱AMP):AMP是AMS在客戶端進(jìn)程的一個(gè)代理,通過(guò)AMP里面的方法請(qǐng)求AMS
Instrumentation: Instrumentaion是一個(gè)工具類,一個(gè)大管家。當(dāng)它被啟用時(shí),系統(tǒng)先創(chuàng)建它,再通過(guò)它來(lái)創(chuàng)建其他組件;另外,系統(tǒng)和組件之間的交互也將通過(guò)Instrumentation來(lái)傳遞,這樣,Instrumentation就能監(jiān)測(cè)系統(tǒng)和這些組件的交互情況了。在實(shí)際使用中,我們可以創(chuàng)建Instrumentation的派生類來(lái)進(jìn)行相應(yīng)的處理。Android中Junit的使用到了Intrstrumentation
OK,現(xiàn)在我們知道,Activity是如何向AMS發(fā)出startActivity這個(gè)請(qǐng)求了,這意味著Activity可以與AMS進(jìn)行通信,但是AMS卻不能與Activity通信,Binder是單向的,所以在Activity發(fā)出請(qǐng)求之后,AMS需要通知Activity發(fā)生狀態(tài)改變,要做到這一點(diǎn),自然就在AMS到Activity這個(gè)過(guò)程建立一個(gè)Binder,如下:
大致過(guò)程就是,SystemServer進(jìn)程在收到請(qǐng)求后,再通過(guò)IPC向應(yīng)用進(jìn)程發(fā)送scheduleLaunchActivity請(qǐng)求,應(yīng)用進(jìn)程的binder線程(ApplicationThread)在收到請(qǐng)求后,通過(guò)handler向主線程發(fā)送LAUNCH_ACTIVITY消息,主線程在收到Message后,創(chuàng)建目標(biāo)Activity,并回調(diào)Activity.onCreate()等方法
對(duì)上面的理解不是太明白,在看下面這張圖,簡(jiǎn)單多了;AMS到Activity這個(gè)過(guò)程建立了一個(gè)Binder,Activity到AMS這個(gè)過(guò)程也建立了一個(gè)Binder,這就能相互通信了
上圖就是Activity與AMS之間的雙向Binder連接, (備注:這個(gè)就是理解Activity啟動(dòng)流程的指南針,不記住這個(gè),復(fù)雜的啟動(dòng)流程會(huì)讓你暈頭轉(zhuǎn)向);Activity用IActivityManager提供的API向AMS提出執(zhí)行某個(gè)動(dòng)作的請(qǐng)求(本例中是啟動(dòng)RemoteService),AMS通過(guò)IApplicationThread提供的API來(lái)控制Activity所在的應(yīng)用程序,這些API包括schedulePauseActivity()、scheduleStopActivity()等
IActivityManager接口定義的API,啟動(dòng)四大組件的等多種請(qǐng)求都在里面
IApplicationThread接口定義的API,一看就比IActivityManager高逼格一點(diǎn),IActivityManager好多方法是start開(kāi)頭,表示去AMS請(qǐng)求,IApplicationThread以schedule開(kāi)頭,表示對(duì)Activity進(jìn)行調(diào)度
分析到這里,我們不知不覺(jué)間忽略了兩個(gè)問(wèn)題,那就是啟動(dòng)Activity至少需要兩個(gè)前提
第一是,應(yīng)用進(jìn)程存在,第二AMS已經(jīng)初始化完畢; 在調(diào)用startActivity方法時(shí)候,如果我們的應(yīng)用進(jìn)程不存在,Activity能啟動(dòng)嗎,當(dāng)然是不能的,比如點(diǎn)擊桌面圖標(biāo)的時(shí)候,這個(gè)時(shí)候需要先創(chuàng)建進(jìn)程。關(guān)于Zygote孵化應(yīng)用進(jìn)程,這個(gè)暫時(shí)不說(shuō),先看看AMS服務(wù)注冊(cè)
三、AMS服務(wù)注冊(cè)
先忽略 Activity調(diào)用ActivityManagerService啟動(dòng)應(yīng)用,直接從SystemServer的main方法說(shuō)起
/** * The main entry point from zygote. */ public static void main(String[] args) { new SystemServer().run(); }
run方法中,調(diào)用了startBootstrapServices
private void startBootstrapServices() { ...... //啟動(dòng)AMS服務(wù) Installer installer = mSystemServiceManager.startService(Installer.class); //請(qǐng)注意這里參數(shù)是Lifecycle,因?yàn)锳MS是在Lifecycle里面new出來(lái)的 mActivityManagerService = mSystemServiceManager.startService( ActivityManagerService.Lifecycle.class).getService(); mActivityManagerService.setSystemServiceManager(mSystemServiceManager); mActivityManagerService.setInstaller(installer); mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class); mActivityManagerService.initPowerManagement(); ...... mActivityManagerService.setSystemProcess(); ...... }
public SystemService startService(String className) { final Class<SystemService> serviceClass; try { serviceClass = (Class<SystemService>)Class.forName(className); } catch (ClassNotFoundException ex) { Slog.i(TAG, "Starting " + className); } return startService(serviceClass); }
繼續(xù)
public <T extends SystemService> T startService(Class<T> serviceClass) { try { final String name = serviceClass.getName(); // 1、創(chuàng)建服務(wù) final T service; try { Constructor<T> constructor = serviceClass.getConstructor(Context.class); // 如果傳進(jìn)來(lái)的是ActivityManagerService.Lifecycle對(duì)象,那么ActivityManagerService就能被創(chuàng)建 service = constructor.newInstance(mContext); } catch (InstantiationException ex) { throw new RuntimeException("Failed to create service " + name + ": service could not be instantiated", ex); } // 2、注冊(cè)服務(wù) mServices.add(service); // 3、啟動(dòng)服務(wù) try { service.onStart(); } catch (RuntimeException ex) { throw new RuntimeException("Failed to start service " + name + ": onStart threw an exception", ex); } return service; } finally { Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); } }
ActivityManagerService.java public static final class Lifecycle extends SystemService { private final ActivityManagerService mService; public Lifecycle(Context context) { super(context); //ActivityManagerService被new出來(lái)了 mService = new ActivityManagerService(context); } @Override public void onStart() { // 啟動(dòng) mService.start(); } public ActivityManagerService getService() { return mService; } }
private void start() { Process.removeAllProcessGroups(); mProcessCpuThread.start(); mBatteryStatsService.publish(mContext); mAppOpsService.publish(mContext); Slog.d("AppOps", "AppOpsService published"); LocalServices.addService(ActivityManagerInternal.class, new LocalService()); }
回到 startBootstrapServices里面調(diào)用的 mActivityManagerService.setSystemProcess();
public void setSystemProcess() { try { ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true); ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats); ServiceManager.addService("meminfo", new MemBinder(this)); ServiceManager.addService("gfxinfo", new GraphicsBinder(this)); ServiceManager.addService("dbinfo", new DbBinder(this)); ...... // 設(shè)置application info LoadedApkinfo 有關(guān) framework-res.apk ApplicationInfo info = mContext.getPackageManager().getApplicationInfo( "android", STOCK_PM_FLAGS); mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader()); //給SystemServer進(jìn)程創(chuàng)建ProcessRecord,adj值,就是將SystemServer進(jìn)程加入到AMS進(jìn)程管理機(jī)制中,跟應(yīng)用進(jìn)程一致 synchronized (this) { ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0); app.persistent = true; app.pid = MY_PID; app.maxAdj = ProcessList.SYSTEM_ADJ; app.makeActive(mSystemThread.getApplicationThread(), mProcessStats); synchronized (mPidsSelfLocked) { mPidsSelfLocked.put(app.pid, app); } updateLruProcessLocked(app, false, null); updateOomAdjLocked(); }
ServiceManager這里面注冊(cè)了很多的服務(wù),可通過(guò)dumpsys <服務(wù)名>命令查看。比如查看CPU信息命令dumpsys cpuinfo,查看graphics信息命令dumpsys gfxinfo
在Android中所有的核心服務(wù),并不是直接給上層使用,都先交給ServiceManager管理,上層使用的時(shí)候可以從ServiceManager獲取,ServiceManager相當(dāng)于一個(gè)路由作用?,F(xiàn)在來(lái)看一張經(jīng)典的圖。其中注冊(cè)服務(wù),獲取服務(wù)以及使用服務(wù),每一次都是一個(gè)完整的Binder IPC過(guò)程,可見(jiàn)理解Binder是多么的重要啊。關(guān)于AMS啟動(dòng)得深入了解
- 注冊(cè)服務(wù):首先AMS注冊(cè)到ServiceManager。AMS所在進(jìn)程(SystemServer)是客戶端,ServiceManager是服務(wù)端
- 獲取服務(wù):Client進(jìn)程使用AMS前,須先向ServiceManager中獲取AMS的代理類AMP。該過(guò)程。AMP所在進(jìn)程(應(yīng)用進(jìn)程)是客戶端,ServiceManager是服務(wù)端
- 使用服務(wù): app進(jìn)程根據(jù)得到的代理類AMP,便可以直接與AMS所在進(jìn)程交互。該過(guò)程,AMP所在進(jìn)程(應(yīng)用進(jìn)程)是客戶端,AMS所在進(jìn)程(SystemServer)是服務(wù)端
到此這篇關(guān)于Android Activity啟動(dòng)流程刨析的文章就介紹到這了,更多相關(guān)Android Activity 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android 自定義view實(shí)現(xiàn)進(jìn)度條加載效果實(shí)例代碼
這篇文章主要介紹了Android 自定義view實(shí)現(xiàn)進(jìn)度條加載效果實(shí)例代碼,需要的朋友可以參考下2017-08-08Android適配利用webview加載后圖片顯示過(guò)大的問(wèn)題解決
這篇文章主要給大家介紹了關(guān)于Android適配利用webview加載后圖片顯示過(guò)大問(wèn)題的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)各位Android開(kāi)發(fā)者們具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07Android自定義WheelView地區(qū)選擇三級(jí)聯(lián)動(dòng)
這篇文章主要為大家詳細(xì)介紹了Android自定義WheelView地區(qū)選擇三級(jí)聯(lián)動(dòng)的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02解決Error:All flavors must now belong to a named flavor dimens
這篇文章主要介紹了解決Error:All flavors must now belong to a named flavor dimension. Learn more at https://d.android.com,需要的朋友可以參考下2017-11-11android車(chē)牌識(shí)別系統(tǒng)EasyPR使用詳解
這篇文章主要為大家詳細(xì)介紹了android車(chē)牌識(shí)別系統(tǒng)EasyPR使用,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12在Android設(shè)備上搭建Web服務(wù)器的方法
本篇文章主要介紹了在Android設(shè)備上搭建Web服務(wù)器的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-04-04Android Spinner與適配器模式詳解及實(shí)例代碼
這篇文章主要介紹了Android Spinner與適配器模式詳解相關(guān)資料,并附代碼實(shí)例,需要的朋友可以參考下2016-10-10Android Dialog 動(dòng)畫(huà)實(shí)例詳解
這篇文章主要介紹了Android Dialog 動(dòng)畫(huà)實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-04-04Android EditText默認(rèn)不彈出輸入法的實(shí)現(xiàn)方法
下面小編就為大家分享一篇Android EditText默認(rèn)不彈出輸入法的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-01-01