概述
安卓开发的程序猿都知道四大组件之一的Activity
的重要性,但可能有很多人并不了解Activity
的创建流程和声生命周期调用流程,只是在运用上行云流水。
那么希望这篇文章对那些还不够了解Activity
的同志们来说能有所帮助。
注:以下源码基于Android11
Android入口函数
在Java程序里,项目的入口函数是main函数,这个想必大家也都知道,那么我们安卓项目又是怎么启动的呢?对,不要怀疑,在我们开发的安卓项目中,也是有一个入口main
函数,安卓中这个main
函数在源码ActivityThread.java
类中:
//ActivityThread.java
public static void main(String[] args) {
...此处省略一万个字母
}
是不是很眼熟,跟Java中一样。当我们点击手机屏幕上的App图标开启应用的时候,Android首先调用的是这个main
方法,Application
和Activity
就在这个main
函数中创建。
源码分析
接下来我们就进入源码分析环节,直接看mian
方法里面的源码:
//ActivityThread.java
public static void main(String[] args) {
...
//为主线程创建Looper
Looper.prepareMainLooper();
long startSeq = 0;
if (args != null) {
for (int i = args.length - 1; i >= 0; --i) {
if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
startSeq = Long.parseLong(
args[i].substring(PROC_START_SEQ_IDENT.length()));
}
}
}
//1.创建ActivityThread
ActivityThread thread = new ActivityThread();
//2.将当前app与Android系统的AMS服务连接起来,记住此处attach方法的第一个参数
thread.attach(false, startSeq);
...
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
上面注释1的部分创建了ActivityThread
,然后在注释2的部分调用了attach
方法,接下来我们点进thread.attach(false, startSeq)
方法里面继续看:
//ActivityThread.java
private void attach(boolean system, long startSeq) {
if (!system) {
...
//1.获取AMS的本地代理对象IActivityManager
final IActivityManager mgr = ActivityManager.getService();
try {
//2.绑定Application
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
...
} else {
...
}
}
在上面的attach
方法里面,注释1的部分,通过AIDL
,获取了AMS的本地代理对象IActivityManager
,它是作为应用进程请求系统进程的接口,实现跟AMS服务跨进程通信(通过AIDL实现跨进程通信)。然后上面注释2的部分通过IActivityManager
实例调用attachApplication
方法,该方法主要是绑定Application,让AMS跟Application连接起来,从而让当前app跟Android系统实现绑定,方便系统管理当前app。接着进入mgr.attachApplication(mAppThread, startSeq)
方法里面:
//ActivityManagerService.java
public final void attachApplication(IApplicationThread thread, long startSeq) {
if (thread == null) {
throw new SecurityException("Invalid application interface");
}
synchronized (this) {
//1.获取pid(系统创建并分配)
int callingPid = Binder.getCallingPid();
//2.获取uid(系统创建并分配)
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
//3.连接Application
attachApplicationLocked(thread, callingPid, callingUid, startSeq);
Binder.restoreCallingIdentity(origId);
}
}
此处需要说明一下,attachApplication
是ActivityManagerService
中的方法,ActivityManagerService
继承了IActivityManager
的Stub
内部类:
当获取到pid和uid之后,紧接着将这两个值作为参数传入到attachApplicationLocked
方法里面,来看看这个方法:
//ActivityManagerService.java
@GuardedBy("this")
private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
int pid, int callingUid, long startSeq) {
//1.进程记录类
ProcessRecord app;
...
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
//2.通过pid获取进程记录类
app = mPidsSelfLocked.get(pid);
}
...
}
...
//通过ProcessRecord实例获取ActiveInstrumentation实例
final ActiveInstrumentation instr2 = app.getActiveInstrumentation();
...
if (app.isolatedEntryPoint != null) {
...
} else if (instr2 != null) {
//当前进程是否处于活动状态
//3.绑定到当前线程
thread.bindApplication(processName, appInfo, providerList,
instr2.mClass,
profilerInfo, instr2.mArguments,
instr2.mWatcher,
instr2.mUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.isPersistent(),
new Configuration(app.getWindowProcessController().getConfiguration()),
app.compat, getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, autofillOptions, contentCaptureOptions,
app.mDisabledCompatChanges);
} else {
//4.绑定到当前线程
thread.bindApplication(processName, appInfo, providerList, null, profilerInfo,
null, null, null, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.isPersistent(),
new Configuration(app.getWindowProcessController().getConfiguration()),
app.compat, getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, autofillOptions, contentCaptureOptions,
app.mDisabledCompatChanges);