这是我参与8月更文挑战的第1天,活动详情查看:8月更文挑战
之前的学习记录都是在自己的本地,借着掘金的这次8月活动的机会,也挑战一下自己,开始坚持写点东西。各位看官点点赞,小弟先谢过。
本文分析的源代码基于 android30
代码执行时序图
始于main()方法
点击icon启动一个APP的行为就是启动一个进程,在Java的世界里,一切始于main方法。SDK里的main方法在类 ActivityThread中。
[1]
android.app.ActivityThread
public static void main(String[] args) {
......
Looper.prepareMainLooper();
......
关键代码
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
......
Looper.loop();
......
创建ActivityThread实例调用attach方法
[2]
android.app.ActivityThread
private void attach(boolean system, long startSeq){
......
final IActivityManager mgr = ActivityManager.getService();
try {
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
......
}
这里提一下ActivityManager.getService()在28(可能更早)之前代码表现为
ActivityManagerNative.getDefault()
都是通过AIDL的方式,获取ActivityManagerService的实例 具体看一下ActivityManager类下的getService()方法
[3]
android.app.ActivityManager
@UnsupportedAppUsage
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
@UnsupportedAppUsage
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
返回了一个IActivityManager.Stub的类型,而ActivityManagerService类确实继承了IActivityManager.Stub,单凭这个并不能确定ActivityManager.getService() 一定返回了ActivityManagerService,虽然网上其他文章一到这就说熟悉AIDL的人就看明白了。。反正我是没看明白,但是当我确定ActivityManagerService类下确实有attachApplication方法时,我可以确定 在thread.attach中ActivityManager.getService() 返回的就是ActivityManagerService类型。
ActivityManagerService开始干活
[4]
com.android.server.am.ActivityManagerService
public class ActivityManagerService extends IActivityManager.Stub
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
......
@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
if (thread == null) {
throw new SecurityException("Invalid application interface");
}
synchronized (this) {
int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
关键代码
attachApplicationLocked(thread, callingPid, callingUid, startSeq);
Binder.restoreCallingIdentity(origId);
}
}
......
}
在attachApplication方法中,第一个参数是IApplicationThread类型,具体实现类是ApplicationThread,他是ActivityThread的一个内部类
private class ApplicationThread extends IApplicationThread.Stub {
......
}
ApplicationThread这个类很关键,内部承担了最后发送Activity生命周期、及其它一些消息的任务。多提一嘴,在ActivityThread还有另一个关键的内部类H
class H extends Handler {
public static final int BIND_APPLICATION = 110;
@UnsupportedAppUsage
public static final int EXIT_APPLICATION = 111;
......
这个H就是一个Handler,内部是安卓四大组件包括其他重要流程的所有处理执行者。ApplicationThread发送的消息,最后也是在H中进行处理。
回到[2]处看到
mgr.attachApplication(mAppThread, startSeq);
传入的mAppThread也就是刚刚说的ApplicationThread实例,可以看到mAppThread是ActivityThread的一个成员变量,并且是final类型的,这表明系统不希望这个变量中途被修改,可见这个变量具有特定而十分重要的作用。
@UnsupportedAppUsage
final ApplicationThread mAppThread = new ApplicationThread();
继续[4]往后看,执行了attachApplicationLocked
com.android.server.am.ActivityManagerService
@GuardedBy("this")
private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
int pid, int callingUid, long startSeq) {
......
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);
......
}
这个方法很长,但是关键代码是执行ApplicationThread中的bindApplication方法。
ActivityThread ->ActivityManagerService->ApplicationThread 代码终于转到了ApplicationThread,也就是前面说的,最后发送消息的地方
package android.app;
ApplicationThread发消息
[5]
android.app.ApplicationThread
@Override
public final void bindApplication(String processName, ApplicationInfo appInfo,
ProviderInfoList providerList, ComponentName instrumentationName,
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableBinderTracking, boolean trackAllocation,
boolean isRestrictedBackupMode, boolean persistent, Configuration config,
CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
String buildSerial, AutofillOptions autofillOptions,
ContentCaptureOptions contentCaptureOptions, long[] disabledCompatChanges) {
......
关键代码
sendMessage(H.BIND_APPLICATION, data);
}
所以就是发送了一个H.BIND_APPLICATION的消息,接下来就看H接受到这个消息是怎么处理的就行了。
万年老大哥H
android.app.ApplicationThread
......
class H extends Handler {
......
public void handleMessage(Message msg) {
......
switch (msg.what) {
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,"bindApplication");
AppBindData data = (AppBindData)msg.obj;
关键代码
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
......
}
}
@UnsupportedAppUsage
private void handleBindApplication(AppBindData data) {
......
try {
1 通过反射获取Instrumentation
final ClassLoader cl = instrContext.getClassLoader();
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName()).newInstance();
} catch (Exception e) {
throw new RuntimeException(
"Unable to instantiate instrumentation "
+ data.instrumentationName + ": " + e.toString(), e);
}
......
Application app;
......
try {
// If the app is being launched for full backup or restore, bring it up in
// a restricted environment with the base application class.
2.创建Application(内部也是反射)
app = data.info.makeApplication(data.restrictedBackupMode, null);
......
if (!data.restrictedBackupMode) {
if (!ArrayUtils.isEmpty(data.providers)) {
初始化ContentProvider
installContentProviders(app, data.providers);
}
}
try {
3.初始化Application
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
}finally {
......
}
}
......
}
- Instrumentation 类主要用来监控应用程序与系统交互,是一个很重要的类。Appilcation,Activityd的创建以及生命周期的控制也在这
流程也是比较清晰的,1处通过反射获取Instrumentation类实例,2处通过反射获取Application实例,3处调用Instrumentation的callApplicationOnCreate方法完成Application的初始化
在创建Application和初始化Application 有一个初始化ContentProvider的操作,可以留意下,以后的文章会细讲
Instrumentation监控应用程序与系统交互
先看callApplicationOnCreate方法
android.app.Instrumentation
public void callApplicationOnCreate(Application app) {
app.onCreate();
}
很简单,调用Application的onCreate() 完成初始化。 那剩下的问题就是第二步如何获创建Application的。 这个data是handleBindApplication方法唯一的参数,可以看到是AppBindData类型的,那直接去这个类里看看他的info是什么类型就可以找到makeApplication方法的具体执行了。
android.app.ActivityThread
......
static final class AppBindData {
@UnsupportedAppUsage
AppBindData() {
}
@UnsupportedAppUsage
LoadedApk info;
......
}
居然也是ActivityThread的内部类,可以看到info是LoadedApk类型的。直接点进去找makeApplication方法
android.app.LoadedApk
@UnsupportedAppUsage
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
......
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
......
return app;
}
熟悉的Instrumentation,现在看来Application的创建和初始化都是在Instrumentation处理了。
android.app.Instrumentation
public Application newApplication(ClassLoader cl, String className, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
关键代码
Application app = getFactory(context.getPackageName())
.instantiateApplication(cl, className);
app.attach(context);
return app;
}
private AppComponentFactory getFactory(String pkg) {
......
LoadedApk apk = mThread.peekPackageInfo(pkg, true);
// This is in the case of starting up "android".
if (apk == null) apk = mThread.getSystemContext().mPackageInfo;
return apk.getAppFactory();返回了一个AppComponentFactory
}
可以看到,是在AppComponentFactory中的instantiateApplication返回完成instantiateApplication的创建
android.app.AppComponentFactory
public @NonNull Application instantiateApplication(@NonNull ClassLoader cl,
@NonNull String className)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return (Application) cl.loadClass(className).newInstance();
}
和前面创建Instrumentation一样,也是通过反射去创建Application
至此,Application的创建和初始化已经完成,当Application初始化完成后,系统会更具Manifests中的配置的启动Activity发送一个Intent去启动相应的Activity。
总结
- 在ActivityThread类里的main方法创建ActivityThread实例调用attach方法
- attach方法内部通过AIDL的方式获取ActivityManagerService实例,调用attachApplication方法,这样就将ApplicationThread的实例传到了ActivityManagerService中处理
- attachApplication方法内部通过attachApplicationLocked方法调用了ApplicationThread的bindApplication方法,流程又到了ApplicationThread中
- bindApplication方法内部发送了消息H.BIND_APPLICATION,于是流程转到H中
- 在H中对于H.BIND_APPLICATION消息处理的方式是handleBindApplication,其内部通过反射获取Instrumentation和Application实例,最后调用Instrumentation的callApplicationOnCreate方法完成Application的初始化
后言
-
为什么代码中省略了那么多代码,只留关键行。因为代码太多,全都复制下来很难找到重点,阅读者也会视觉疲劳。其次篇幅也会过程。
-
一个方法那么长为什么你能找到关键代码。并不是我能找到关键代码,我也是站在巨人的肩膀上,阅读查阅过资料,理清了主要流程。所以在新的Android30中也能找到关键点。对于忽略了的代码。绝大部分我也不知道具体的意义,我也不想知道。因为过于纠结细节,会导致“迷路”。