大致流程
详细流程
进程的启动过程及Application对象的创建过程分析
一个App系统发起启动命令,一直到启动起来,它的第一步就是要启动一个App所对应的进程,该进程承载了我们将要运行的业务。
ActivityThread的main()方法和attach()方法
ActivityThread在我们的Android系统中,是一个非常重要的类,它同时也代表了我们App运行所对应的主线程。那么一个进程启动,就是从ActivityThread类的main函数开始的。
代码位置:/frameworks/base/core/java/android/app/ActivityThread.java
入口函数main
ActivityThread在App启动及运行过程中一个非常重要的类。ActivityThread的main方法是App的入口方法,ActivityThread代表了App的主线程或UI线程。
public static void main(String[] args) {
……
Process.setArgV0("<pre-initialized>"); //设置进程参数
Looper.prepareMainLooper();
……
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
……
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
主要进行了以下几个操作:
- 初始化MainLooper。
- 创建ActivityThread实例对象,并调用attach实例方法。
- 初始化主线程的Handler,并赋值给sMainThreadHandler属性。
- 主进程进入Looper循环。
main方法执行过后,App所在进程就拥有了一个具有MainLooper,并且已经进入Looper循环监听的这么一个主线程了。ActivityThread对象也进行了相应的创建和初始化设置,主线程的Handler也进行了初始化工作,随时都准备接受消息,进行消息处理的工作了。
ActivityThread的构造函数
ActivityThread构造方法调用时,会初始化ResourcesManager对象。
ActivityThread() {
mResourcesManager = ResourcesManager.getInstance();
}
ActivityThread的attach方法 ActivityThread的attach方法:
private void attach(boolean system, long startSeq) {
sCurrentActivityThread = this;
mSystemThread = system; //是否是系统进程,我们的App这个值是false
if (!system) {
ViewRootImpl.addFirstDrawHandler(new Runnable() {
@Override
public void run() {
ensureJitEnabled();
}
});
android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
UserHandle.myUserId());
RuntimeInit.setApplicationObject(mAppThread.asBinder());//ApplicationThread的binder对象,用于通信
final IActivityManager mgr = ActivityManager.getService();//获取AMS服务
try {
mgr.attachApplication(mAppThread, startSeq);//远程调用AMS服务的attachApplication来启动一个Application
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
// Watch for getting close to heap limit. 注册GC检测器,当可用内存较低时,清理隐藏Activity
BinderInternal.addGcWatcher(new Runnable() {
@Override public void run() {
if (!mSomeActivitiesChanged) {
return;
}
Runtime runtime = Runtime.getRuntime();
long dalvikMax = runtime.maxMemory();
long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
if (dalvikUsed > ((3*dalvikMax)/4)) {
if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
+ " total=" + (runtime.totalMemory()/1024)
+ " used=" + (dalvikUsed/1024));
mSomeActivitiesChanged = false;
try {
mgr.releaseSomeActivities(mAppThread); //执行隐藏Activity栈的内存清理
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
});
} else {
// Don't set application object here -- if the system crashes,
// we can't display an alert, we just want to die die die.
android.ddm.DdmHandleAppName.setAppName("system_process",
UserHandle.myUserId());
try {
mInstrumentation = new Instrumentation();
mInstrumentation.basicInit(this);
ContextImpl context = ContextImpl.createAppContext(
this, getSystemContext().mPackageInfo);
mInitialApplication = context.mPackageInfo.makeApplication(true, null);
mInitialApplication.onCreate();
} catch (Exception e) {
throw new RuntimeException(
"Unable to instantiate Application():" + e.toString(), e);
}
}
// add dropbox logging to libcore
DropBox.setReporter(new DropBoxReporter());
ViewRootImpl.ConfigChangedCallback configChangedCallback
= (Configuration globalConfig) -> {
synchronized (mResourcesManager) {
// We need to apply this change to the resources immediately, because upon returning
// the view hierarchy will be informed about it.
if (mResourcesManager.applyConfigurationToResourcesLocked(globalConfig,
null /* compat */)) {
updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
mResourcesManager.getConfiguration().getLocales());
// This actually changed the resources! Tell everyone about it.
if (mPendingConfiguration == null
|| mPendingConfiguration.isOtherSeqNewer(globalConfig)) {
mPendingConfiguration = globalConfig;
sendMessage(H.CONFIGURATION_CHANGED, globalConfig);
}
}
}
};
ViewRootImpl.addConfigCallback(configChangedCallback);
}
参数:
system:是否是系统进程。 startSeq:通过命令行传递过来的值(PROC_START_SEQ_IDENT),默认值为0。
逻辑解析:
- 首先检测该进程是否是系统进程,在这里我们重点来看非系统进程。
- RuntimeInit.setApplicationObject传递ApplicationThread的binder对象,为进程通信做准备。
- 远程调用AMS服务的attachApplication来启动一个Application,我们后面重点来分析。
- 注册GC检测器,当可用内存较低时,清理隐藏Activity。 ViewRootImpl.ConfigChangedCallback注册配置改变的监听。
清理隐藏Activity栈
我们首先来看下上面的第4点,注册GC检测器,当可用内存较低时,清理隐藏Activity。
我们来分析它的技术实现。
BinderInternal.addGcWatcher注册一个GC监听器,用于在内存使用率达到一定比例时,启动隐藏Activity栈的清理工作,以释放更多内存。
我们来看这个GC监听器是如何注册生效的?
- BinderInternal实现
/frameworks/base/core/java/com/android/internal/os/BinderInternal.java
static WeakReference<GcWatcher> sGcWatcher
= new WeakReference<GcWatcher>(new GcWatcher());
static ArrayList<Runnable> sGcWatchers = new ArrayList<>();
static Runnable[] sTmpWatchers = new Runnable[1];
static long sLastGcTime;
static final BinderProxyLimitListenerDelegate sBinderProxyLimitListenerDelegate =
new BinderProxyLimitListenerDelegate();
static final class GcWatcher {
@Override
protected void finalize() throws Throwable {
handleGc();
sLastGcTime = SystemClock.uptimeMillis();
synchronized (sGcWatchers) {
sTmpWatchers = sGcWatchers.toArray(sTmpWatchers);
}
for (int i=0; i<sTmpWatchers.length; i++) {
if (sTmpWatchers[i] != null) {
sTmpWatchers[i].run();
}
}
sGcWatcher = new WeakReference<GcWatcher>(new GcWatcher());
}
}
public static void addGcWatcher(Runnable watcher) {
synchronized (sGcWatchers) {
sGcWatchers.add(watcher);
}
}
逻辑解析:
它的原理是利用了finalize()方法来实现的。具体如下:
- 首先注册一个弱引用的GcWatcher对象,当GC回首弱引用时,就会触发它的finalize()方法;
- sTmpWatchers数组中存放了需要处理的注册监听,它是一个Runnable数组;
- 在finalize()方法中,我们遍历sTmpWatchers数组,调用Runnable对象的run()方法执行监听事件;
- 执行完毕通知事件之后,之前的GcWatcher对象已经作为垃圾回收掉了,我们需要重新生成一个作为下一次GC的监听入口。
执行隐藏Activity内存清理的条件是dalvikUsed > ((3*dalvikMax)/4),也即是当前已使用内存大于总内存的3/4时,满足执行条件。
执行清理的工作是由AMS的releaseSomeActivities方法来进行的。
- releaseSomeActivities方法
ActivityManagerService的releaseSomeActivities方法:
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
@Override
public void releaseSomeActivities(IApplicationThread appInt) {
synchronized(this) {
final long origId = Binder.clearCallingIdentity();
try {
ProcessRecord app = getRecordForAppLocked(appInt); //从最近运行App列表中找到对应的ProcessRecord对象
mStackSupervisor.releaseSomeActivitiesLocked(app, "low-mem"); //执行隐藏Activity栈的清理工作
} finally {
Binder.restoreCallingIdentity(origId);
}
}
}
这里调用了ActivityStackSupervisor的实例方法releaseSomeActivitiesLocked来进行Activity工作栈的操作。
代码位置:frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
回收规则:
对于单栈(TaskRecord)应用,在前台的时候,所有界面都不会被回收,只有多栈情况下,系统才会回收不可见栈的Activity。 ActivityStack利用maxTasks 保证,最多清理tasks.size() / 4,最少清理1个TaskRecord。
ActivityManagerService的attachApplication()方法
ActivityManagerService的attachApplication()方法是进程Application创建的核心逻辑,我们来分析它的实现过程。
ActivityThread的attach方法,远程调用AMS服务的attachApplication来启动一个Application,这里的参数为ApplicationThread的实例,ApplicationThread类是ActivityThread的内部类,负责与AMS等服务进行Binder通信。
@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid, callingUid, startSeq);
Binder.restoreCallingIdentity(origId);
}
}
这里调用了attachApplicationLocked方法:
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid, int callingUid, long startSeq) {
// Find the application record that is being attached... either via
// the pid if we are running in multiple processes, or just pull the
// next app record if we are emulating process with anonymous threads.
ProcessRecord app;
……
//获取进程所对应的ProcessRecord对象。
if (app == null) {
……
//获取失败,退出进程
return false;
}
// If this application record is still attached to a previous
// process, clean it up now.
if (app.thread != null) {//如果该ProcessRecord对象之前attached到了一个进程,则进行清理操作
handleAppDiedLocked(app, true, true);
}
……
final String processName = app.processName;
……
//注册Binder死亡监听
……
//以下进行ProcessRecord对象的相关初始化操作
app.makeActive(thread, mProcessStats);//绑定ApplicationThread对象
app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ;//进程优先级设置
app.curSchedGroup = app.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.forcingToImportant = null;
updateProcessForegroundLocked(app, false, false);//前台服务相关设置
app.hasShownUi = false;
app.debugging = false;
app.cached = false;
app.killedByAm = false;
app.killed = false;
// We carefully use the same state that PackageManager uses for
// filtering, since we use this flag to decide if we need to install
// providers when user is unlocked later
app.unlocked = StorageManager.isUserKeyUnlocked(app.userId);
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
……
provider相关处理
……
……
try {
……
ApplicationInfo appInfo = app.instr != null ? app.instr.mTargetInfo : app.info;
app.compat = compatibilityInfoForPackageLocked(appInfo);
……
//Build.SERIAL获取,Android P以下可以获取到
……
//Instrumentation处理,多进程的使用同一个Instrumentation(后续进程并入第一个进程)。
……
if (app.isolatedEntryPoint != null) {
// This is an isolated process which should just call an entry point instead of
// being bound to an application.
thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);
} else if (app.instr != null) {//Instrumentation不为空
thread.bindApplication(processName, appInfo, providers,
app.instr.mClass,
profilerInfo, app.instr.mArguments,
app.instr.mWatcher,
app.instr.mUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(getGlobalConfiguration()), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, isAutofillCompatEnabled);
} else {
thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
null, null, null, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(getGlobalConfiguration()), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, isAutofillCompatEnabled);
}
……
checkTime(startTime, "attachApplicationLocked: immediately after bindApplication");
updateLruProcessLocked(app, false, null);
checkTime(startTime, "attachApplicationLocked: after updateLruProcessLocked");
app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
} catch (Exception e) {
……
return false;
}
// 从正在启动进程列表删除
mPersistentStartingProcesses.remove(app);
……
if (normalMode) {
try {
if (mStackSupervisor.attachApplicationLocked(app)) {//查看顶部可展示Activity是否正在等待在当前进程中运行。也就是处理Activity展示
didSomething = true;
}
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
badApp = true;
}
}
// Find any services that should be running in this process...
if (!badApp) {
try {
didSomething |= mServices.attachApplicationLocked(app, processName); //处理需要运行在当前进程中的Service
checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked");
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
badApp = true;
}
}
// Check if a next-broadcast receiver is in this process...
//处理需要运行在当前进程中的broadcast receiver
if (!badApp && isPendingBroadcastProcessLocked(pid)) {
try {
didSomething |= sendPendingBroadcastsLocked(app);
checkTime(startTime, "attachApplicationLocked: after sendPendingBroadcastsLocked");
} catch (Exception e) {
// If the app died trying to launch the receiver we declare it 'bad'
Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e);
badApp = true;
}
}
……
if (!didSomething) {
updateOomAdjLocked();
checkTime(startTime, "attachApplicationLocked: after updateOomAdjLocked");
}
return true;
}
逻辑解析:
- 获取进程所对应的ProcessRecord对象。
- 注册Binder死亡监听
- 进行ProcessRecord对象的相关初始化操作
- Instrumentation处理,多进程的使用同一个Instrumentation(后续进程并入第一个进程)。
- 调用thread.bindApplication真正启动Application。这里是Application的启动过程。
- 处理Activity显示、Service、BroadcastReceiver等。这里涉及到Activity的启动过程,我们后面来分析。
调用mStackSupervisor.attachApplicationLocked(app)启动Activity栈中,需要展示的Activity页面。
这里的thread.bindApplication方法调用,是真正创建Application对象的地方,我们重点来看。
Application的启动
在ActivityManagerService中的attachApplicationLocked方法在服务AMS进程中,远程调用当前进程的ApplicationThread的bindApplication来创建并启动App所对应的的Application。
ApplicationThread继承自IApplicationThread.Stub,这里也证明了它的重要功能就是实现AMS与Client进行间进行Binder通信使用。
ApplicationThread的bindApplication方法
bindApplication方法: /frameworks/base/core/java/android/app/ActivityThread.java
public final void bindApplication(String processName, ApplicationInfo appInfo,
List<ProviderInfo> providers, 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, boolean autofillCompatibilityEnabled) {
if (services != null) {
…… 调试日志
// Setup the service cache in the ServiceManager
ServiceManager.initServiceCache(services);
}
setCoreSettings(coreSettings);
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.providers = providers;
data.instrumentationName = instrumentationName;
data.instrumentationArgs = instrumentationArgs;
data.instrumentationWatcher = instrumentationWatcher;
data.instrumentationUiAutomationConnection = instrumentationUiConnection;
data.debugMode = debugMode;
data.enableBinderTracking = enableBinderTracking;
data.trackAllocation = trackAllocation;
data.restrictedBackupMode = isRestrictedBackupMode;
data.persistent = persistent;
data.config = config;
data.compatInfo = compatInfo;
data.initProfilerInfo = profilerInfo;
data.buildSerial = buildSerial;
data.autofillCompatibilityEnabled = autofillCompatibilityEnabled;
sendMessage(H.BIND_APPLICATION, data);
}
逻辑解析:
- services保存了基础的一些系统Service服务,这里调用ServiceManager的initServiceCache方法,将这些Serivce服务添加到SM中的缓存列表"sCache"中。
- 生成AppBindData对象,并设置Application的初始化信息。
- 发送BIND_APPLICATION消息,继续处理。
ActivityThread的handleBindApplication方法
H的handleMessage对BIND_APPLICATION消息进行处理:
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
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;
}
这里直接调用handleBindApplication方法进行Application的正式启动过程。
handleBindApplication:
private void handleBindApplication(AppBindData data) {
……
mBoundApplication = data;//mBoundApplication赋值
……
Process.setArgV0(data.processName);//设置进程名称
android.ddm.DdmHandleAppName.setAppName(data.processName,
UserHandle.myUserId());
VMRuntime.setProcessPackageName(data.appInfo.packageName);//设置相关包名
……
//解码Bitmap使用的规则,Android P之前使用BitmapFactory,之后使用ImageDecoder
ImageDecoder.sApiLevel = data.appInfo.targetSdkVersion;
//重置系统时区
TimeZone.setDefault(null);
……
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);//生成LoadedApk对象
……
// 设置Build的SERIAL属性值
try {
Field field = Build.class.getDeclaredField("SERIAL");
field.setAccessible(true);
field.set(Build.class, data.buildSerial);
} catch (NoSuchFieldException | IllegalAccessException e) {
/* ignore */
}
……
//debug相关设置
……
//设置Instrumentation
……
//创建appContext对象
……
if (ii != null) {
……
//创建Instrumentation对象,并执行init初始化
final ComponentName component = new ComponentName(ii.packageName, ii.name);
mInstrumentation.init(this, instrContext, appContext, component,
data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
……
} else {
mInstrumentation = new Instrumentation();
mInstrumentation.basicInit(this);
}
……
// 在进程启动过程中或Provider安装过程中,暂时允许访问磁盘权限
Application app;
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy();
try {
// 创建Application对象
app = data.info.makeApplication(data.restrictedBackupMode, null);
……
mInitialApplication = app;
// don't bring up providers in restricted mode; they may depend on the
// app's custom Application class
if (!data.restrictedBackupMode) {//如果应用正在安装或恢复这类特殊状态,restrictedBackupMode值为true。这里正常情况下为false
if (!ArrayUtils.isEmpty(data.providers)) {
installContentProviders(app, data.providers); //此处安装ContentProvider
// For process that contains content providers, we want to
// ensure that the JIT is enabled "at some point".
mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
}
}
// 在providers安装之后,执行Instrumentation对象的onCreate方法,启动Instrumentation线程
try {
mInstrumentation.onCreate(data.instrumentationArgs);
}
……
try {
mInstrumentation.callApplicationOnCreate(app);//通过callApplicationOnCreate,调用Application对象的onCreate方法
}
……
} finally {
……
}
……
// 预加载字体资源相关处理
}
逻辑解析
这个方法逻辑非常多,我们来看它主要做了哪些处理:
- 设置mBoundApplication = data(参数AppBindData对象)。
- Process.setArgV0(data.processName)设置进程名称。
- VMRuntime.setProcessPackageName(data.appInfo.packageName)设置包名。
- 设置解码Bitmap使用的规则。
- 重置系统时区。
- 生成LoadedApk对象。
- 设置Build的SERIAL属性值。
- 设置Instrumentation。
- 创建appContext对象。
- 创建Instrumentation对象,并初始化。
- 在进程启动过程中或Provider安装过程中,设置暂时允许访问磁盘权限标志。
- 创建Application对象。
- 安装ContentProvider。
- 在providers安装之后,执行Instrumentation对象的onCreate方法,启动Instrumentation线程。
- 通过Instrumentation对象的callApplicationOnCreate,调用Application对象的onCreate方法。
- 预加载字体资源相关处理。
执行完handleBindApplication方法后,我们的应用程序也就启动完成了。
创建Application对象该过程非常重要,我们详细分析。
Application对象的创建
在ActivityThread对象的handleBindApplicaiton方法中,创建了Application对象,代码:
// 创建Application对象
app = data.info.makeApplication(data.restrictedBackupMode, null);
这里data是一个AppBindData对象,它的info属性是一个LoadedApk对象,这样我们就知道,这里调用的其实是LoadedApk对象的makeApplicaiton方法。
LoadedApk类的makeApplication方法
/frameworks/base/core/java/android/app/LoadedApk.java
public Application makeApplication(boolean forceDefaultAppClass, //如果应用正在安装或恢复这类特殊状态,restrictedBackupMode值(这里是第一个参数)为true,正常启动应用,这里是false。
Instrumentation instrumentation) { //instrumentation参数这里传递进来的是null
if (mApplication != null) { //已经存在,直接返回
return mApplication;
}
……
Application app = null;
//设置正在启动的App的Application的类名
String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";
}
try {
//创建并处理ClassLoader对象
java.lang.ClassLoader cl = getClassLoader();
if (!mPackageName.equals("android")) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
"initializeJavaContextClassLoader");
initializeJavaContextClassLoader();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
//创建ContextImpl对象作为application的Context环境
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
//这里调用Instrumentation对象的newApplication方法来创建Application对象。
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app); //ContextImpl对象绑定Application对象
}
……
mActivityThread.mAllApplications.add(app); //添加到mAllApplications列表
mApplication = app;
if (instrumentation != null) { //这里在App启动过程中传递进来的是null,不会走此逻辑
try {
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!instrumentation.onException(app, e)) {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
}
……
// Rewrite the R 'constants' for all library apks.
……
return app;
}
逻辑解析:
如果mApplication已经赋值,则直接返回,否则继续。 设置正在启动的App的Application的类名。 创建并处理ClassLoader对象。 创建ContextImpl对象作为application的Context环境。 调用Instrumentation对象的newApplication方法来创建Application对象,这里的Instrumentation对象是通过ActivityThread来获取的。 ContextImpl对象绑定Application对象。 添加到mAllApplications列表。 接续来看thread.bindApplication真正启动Application方法。
Instrumentation类的newApplication方法
Application对象的创建最终是在Instrumentation对象的newApplication方法中通过反射调用创建的。
public Application newApplication(ClassLoader cl, String className, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
return newApplication(cl.loadClass(className), context);
}
static public Application newApplication(Class<?> clazz, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
Application app = (Application)clazz.newInstance();
app.attach(context);
return app;
}
逻辑解析:
首先通过ClassLoader对象加载Application所对应的类名。 使用Java反射调用,newInstance一个Application对象。 最后调用Application对象的attach方法,参数是context。这里就就是我们熟悉的Application的attach方法了,我们可以在这里处理一些应用程序启动时的一些初始化工作。 至此,我们的Application的创建及启动过程已经分析完成了,详细你也会对此有一个比较清晰的了解。整个过程,涉及到了我们App所在的Client端,也涉及到了ActivityManagerService为代表的Server端,他们之间的通信过程当然是基于Binder了。ApplicationThread作为了Server端调用Client端的一个引用,实现了它们之间的相互通信。
image在Android开发与车载开发,以及framework中起到重要部分,想要更多的Android进阶、车载开发学习。可以参考《Android核心技术手册》里面包含30多个技术模块。有车载开发、Android开发、framework的学习文档。
文末
以前看源码总是乱七八糟的,跳来跳去,还没跟到最后就跟丢了,就算勉强看完整个流程了,过两天又忘记了,再次看依然要花很大的力气,一直都在心里骂谷歌的工程师写的都是什么破代码,后来发现用时序图把源码流程画出来之后清晰多了,一目了然,需要的时候看一下图就清楚了,了解某一个点的细节直接从指定位置开始看源码就行。时序图,以后你就是我女朋友了。
网友评论