網(wǎng)站首頁 編程語言 正文
前言
上篇文章寫到 Service 的啟動過程; 相對來說Activity的啟動過程比Service的啟動過程更為復(fù)雜,其一Activity的生命周期方法比Service多,其二Activity具有啟動模式和返回棧; 寫本文的目的在于更清晰的梳理Activity的啟動過程,加強(qiáng)自己的內(nèi)功修煉,力在以最簡單的方式讓大家理解,跟大家一起學(xué)習(xí)
一、Binder的基本理解
Activity的啟動有多次IPC過程,所以Binder屬于預(yù)備知識,幫助我們更好理解系統(tǒng)的C/S的這種架構(gòu)模式
二、Activity啟動的雙向IPC過程
一般Android各個(gè)應(yīng)用進(jìn)程的啟動都以這樣一條路線,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)程都是它孵化出來的;
- SystemServer進(jìn)程含有一些核心的服務(wù),比如ActivityManagerService,PackageManagerService,WindowManagerService等;
- 各種應(yīng)用進(jìn)程:啟動自己編寫的客戶端應(yīng)用時(shí),有自己的虛擬機(jī)與運(yùn)行環(huán)境。
由此可知應(yīng)用的第一個(gè)Activity的啟動是多個(gè)進(jìn)程相互配合的結(jié)果,多個(gè)進(jìn)程相互配合就少不了使用Binder進(jìn)行IPC了,現(xiàn)在看一次IPC調(diào)用的過程是怎樣的。
上圖大概說明了一次IPC的過程,或許你現(xiàn)在對里面各個(gè)類還不是很清楚,沒關(guān)系,大致了解一下
ActivityManagerService (下文簡稱AMS),AMS是Android中最核心的服務(wù),實(shí)現(xiàn)了ActivityManager,主要負(fù)責(zé)系統(tǒng)中四大組件的啟動、切換、調(diào)度及應(yīng)用進(jìn)程的管理和調(diào)度等工作,AMS提供了一個(gè)ArrayList mHistory來管理所有的Activity,Activity在AMS中的形式是ActivityRecord,Task在AMS中的形式為TaskRecord,進(jìn)程在AMS中的管理形式為ProcessRecord,它在Android中特別重要
ActivityManagerNative (下文簡稱AMN):由于AMS是系統(tǒng)核心服務(wù)在SystemServer進(jìn)程里面,很多API不能直接開放供客戶端使用,所以需要通過IPC的方式,具體是這樣的,ActivityManager類內(nèi)部調(diào)用AMN的getDefault函數(shù)得到一個(gè)ActivityManagerProxy對象,通過它可與AMS通信
ActivityManagerProxy (下文簡稱AMP):AMP是AMS在客戶端進(jìn)程的一個(gè)代理,通過AMP里面的方法請求AMS
Instrumentation: Instrumentaion是一個(gè)工具類,一個(gè)大管家。當(dāng)它被啟用時(shí),系統(tǒng)先創(chuàng)建它,再通過它來創(chuàng)建其他組件;另外,系統(tǒng)和組件之間的交互也將通過Instrumentation來傳遞,這樣,Instrumentation就能監(jiān)測系統(tǒng)和這些組件的交互情況了。在實(shí)際使用中,我們可以創(chuàng)建Instrumentation的派生類來進(jìn)行相應(yīng)的處理。Android中Junit的使用到了Intrstrumentation
OK,現(xiàn)在我們知道,Activity是如何向AMS發(fā)出startActivity這個(gè)請求了,這意味著Activity可以與AMS進(jìn)行通信,但是AMS卻不能與Activity通信,Binder是單向的,所以在Activity發(fā)出請求之后,AMS需要通知Activity發(fā)生狀態(tài)改變,要做到這一點(diǎn),自然就在AMS到Activity這個(gè)過程建立一個(gè)Binder,如下:
大致過程就是,SystemServer進(jìn)程在收到請求后,再通過IPC向應(yīng)用進(jìn)程發(fā)送scheduleLaunchActivity請求,應(yīng)用進(jìn)程的binder線程(ApplicationThread)在收到請求后,通過handler向主線程發(fā)送LAUNCH_ACTIVITY消息,主線程在收到Message后,創(chuàng)建目標(biāo)Activity,并回調(diào)Activity.onCreate()等方法
對上面的理解不是太明白,在看下面這張圖,簡單多了;AMS到Activity這個(gè)過程建立了一個(gè)Binder,Activity到AMS這個(gè)過程也建立了一個(gè)Binder,這就能相互通信了
上圖就是Activity與AMS之間的雙向Binder連接, (備注:這個(gè)就是理解Activity啟動流程的指南針,不記住這個(gè),復(fù)雜的啟動流程會讓你暈頭轉(zhuǎn)向);Activity用IActivityManager提供的API向AMS提出執(zhí)行某個(gè)動作的請求(本例中是啟動RemoteService),AMS通過IApplicationThread提供的API來控制Activity所在的應(yīng)用程序,這些API包括schedulePauseActivity()、scheduleStopActivity()等
IActivityManager接口定義的API,啟動四大組件的等多種請求都在里面
IApplicationThread接口定義的API,一看就比IActivityManager高逼格一點(diǎn),IActivityManager好多方法是start開頭,表示去AMS請求,IApplicationThread以schedule開頭,表示對Activity進(jìn)行調(diào)度
分析到這里,我們不知不覺間忽略了兩個(gè)問題,那就是啟動Activity至少需要兩個(gè)前提
第一是,應(yīng)用進(jìn)程存在,第二AMS已經(jīng)初始化完畢; 在調(diào)用startActivity方法時(shí)候,如果我們的應(yīng)用進(jìn)程不存在,Activity能啟動嗎,當(dāng)然是不能的,比如點(diǎn)擊桌面圖標(biāo)的時(shí)候,這個(gè)時(shí)候需要先創(chuàng)建進(jìn)程。關(guān)于Zygote孵化應(yīng)用進(jìn)程,這個(gè)暫時(shí)不說,先看看AMS服務(wù)注冊
三、AMS服務(wù)注冊
先忽略 Activity調(diào)用ActivityManagerService啟動應(yīng)用,直接從SystemServer的main方法說起
/**
* The main entry point from zygote.
*/
public static void main(String[] args) {
new SystemServer().run();
}
run方法中,調(diào)用了startBootstrapServices
private void startBootstrapServices() {
......
//啟動AMS服務(wù)
Installer installer = mSystemServiceManager.startService(Installer.class);
//請注意這里參數(shù)是Lifecycle,因?yàn)锳MS是在Lifecycle里面new出來的
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)來的是ActivityManagerService.Lifecycle對象,那么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、注冊服務(wù)
mServices.add(service);
// 3、啟動服務(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出來了
mService = new ActivityManagerService(context);
}
@Override
public void onStart() {
// 啟動
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這里面注冊了很多的服務(wù),可通過dumpsys <服務(wù)名>命令查看。比如查看CPU信息命令dumpsys cpuinfo,查看graphics信息命令dumpsys gfxinfo
在Android中所有的核心服務(wù),并不是直接給上層使用,都先交給ServiceManager管理,上層使用的時(shí)候可以從ServiceManager獲取,ServiceManager相當(dāng)于一個(gè)路由作用?,F(xiàn)在來看一張經(jīng)典的圖。其中注冊服務(wù),獲取服務(wù)以及使用服務(wù),每一次都是一個(gè)完整的Binder IPC過程,可見理解Binder是多么的重要啊。關(guān)于AMS啟動得深入了解
- 注冊服務(wù):首先AMS注冊到ServiceManager。AMS所在進(jìn)程(SystemServer)是客戶端,ServiceManager是服務(wù)端
- 獲取服務(wù):Client進(jìn)程使用AMS前,須先向ServiceManager中獲取AMS的代理類AMP。該過程。AMP所在進(jìn)程(應(yīng)用進(jìn)程)是客戶端,ServiceManager是服務(wù)端
- 使用服務(wù): app進(jìn)程根據(jù)得到的代理類AMP,便可以直接與AMS所在進(jìn)程交互。該過程,AMP所在進(jìn)程(應(yīng)用進(jìn)程)是客戶端,AMS所在進(jìn)程(SystemServer)是服務(wù)端
原文鏈接:https://blog.csdn.net/m0_70748845/article/details/126226636
相關(guān)推薦
- 2022-05-26 C++的深淺拷貝和寫時(shí)拷貝你了解嗎_C 語言
- 2022-05-21 C#編程之AOP編程思想_C#教程
- 2023-07-06 Mac安裝python3并配置環(huán)境變量
- 2022-09-05 詳解apache編譯安裝httpd-2.4.54及三種風(fēng)格的init程序特點(diǎn)和區(qū)別_Linux
- 2022-06-21 C++深入探究二階構(gòu)造模式的原理與使用_C 語言
- 2022-08-18 Git多人協(xié)同開發(fā)緊急修復(fù)線上bug操作指南_相關(guān)技巧
- 2022-05-26 openwrt安裝docker并啟動的操作方法_docker
- 2022-06-18 C#多線程的ResetAbort()方法_C#教程
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支