今天看了一下application的启动流程的源代码,避免忘记,先写文章备份下,防止忘记。另外第一次看有可能某些部分不完整或者理解的不正确,以后再补上。
其实一个应用启动运行过程中最核心的类就是ActivityThead了。
首先先了解一下AcitivityThread中的一些成员变量,当然这里只选择一部分我认为是重要的来解释,这些对下文的描述是有帮助的。
private ContextImpl mSystemContext;//系统的context
final Looper mLooper = Looper.myLooper();//looper,既然是activityThread,那么必然有一个looper来对应
final H mH = new H();//对looper对应的handler,继承自handler,只是多了一些成员变量的定义。application的创建等msg都是由这个handler发出的
final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();//记录
final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();//
Application mInitialApplication;//
final ArrayList<Application> mAllApplications = new ArrayList<Application>();//
Instrumentation mInstrumentation;//
final ArrayMap<String, WeakReference<LoadedApk>> mPackages = new ArrayMap<String, WeakReference<LoadedApk>>();//
final ArrayMap<String, WeakReference<LoadedApk>> mResourcePackages = new ArrayMap<String, WeakReference<LoadedApk>>();//
一、
一、构建创建Application的Message并发送
首先会构建Message对象,这个Message中包含AppBindData,该对象含有生成Application的所有数据,用于构建Application。(该部分代码还未看,后续补上)
1.1 AppBindData类
static final class AppBindData { LoadedApk info; String processName; ApplicationInfo appInfo; List<ProviderInfo> providers; ComponentName instrumentationName; Bundle instrumentationArgs; IInstrumentationWatcher instrumentationWatcher; IUiAutomationConnection instrumentationUiAutomationConnection; int debugMode; boolean enableOpenGlTrace; boolean restrictedBackupMode; boolean persistent; Configuration config; CompatibilityInfo compatInfo; /** Initial values for {@link Profiler}. */ ProfilerInfo initProfilerInfo; public String toString() { return "AppBindData{appInfo=" + appInfo + "}"; } }
二、接收Message对象并分发
会通过Handler发送Message,android系统会委托ActivityThread对象的handleMessage(Message msg)方法来处理。
1.首先判断类型,接收AppBindData对象,调用handleBindApplication(data)方法来处理。
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方法
本文重点分析的就是handleBindApplication方法中做了些什么。源码分析start:
2.首先调用getPackageInfoNoCheck方法生成LoaderApk对象。ActivityThread中存在一个
final ArrayMap<String, WeakReference<LoadedApk>> mPackages = new ArrayMap<String, WeakReference<LoadedApk>>();
保存所有的应用和应用对应的LoadedApk。如果存在已经存在LoadedApk对象的话直接返回,否则生成新的。
3.判断是否需要设置应用分辨率密度。(PS:看完之后才知道原来android可以支持对应不同的应用设置不同的分辨率密度)
/** * Switch this process to density compatibility mode if needed. */ if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) == 0) { mDensityCompatMode = true; Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT); } updateDefaultDensity();
4.创建appContext,这是application生成流程中生成的第一个ContextImpl。这个appContext作用感觉主要是作为一种工具类获取生成其他对象所需要的信息。
这里有一个比较大的流程,是用于生成Instrumentation对象的。至于这个对象的作用我大体搜了一下,解释如下:
Android测试环境的核心是一个Instrumentation框架,在这个框架下,你的测试应用程序可以精确控制应用程序。使用Instrumentation,你可以在主程序启动之前,创建模拟的系统对象,如Context;控制应用程序的多个生命周期;发送UI事件给应用程序;在执行期间检查程序状态。Instrumentation框架通过将主程序和测试程序运行在同一个进程来实现这些功能。
大体理解了,由于不涉及到我们的核心内容那个,所以只是粗略看下,不做深入了解。
5.继续往下走,利用appContext获取PackageManager对象,继而获取InstrumentationInfo信息。最后利用InstrumentationInfo给ApplicationInfo赋值。
6.1有了ApplicationInfo instrApp对象之后,获取对应的LoaderApk。方法是
LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,appContext.getClassLoader(), false, true, false);这个方法内部还是逻辑内容还是蛮多的。
方法内有一个
final ArrayMap<String, WeakReference<LoadedApk>> mPackages = new ArrayMap<String, WeakReference<LoadedApk>>();
对象,保存所有的应用和LoadedApk的对应关系。如果存在对应的LoadedApk,则直接使用。否则生成新的。
6.2.利用获取到的LoadedApk对象生成ContextImpl instrContext,这个Context是和当前的Application绑定的,而上面个的appContext绑定的LoadedApk则不是。
6.3.通过反射生成Instrumentation对象。
生成Instrumentation对象的流程结束。
7.继续往下走
if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) { dalvik.system.VMRuntime.getRuntime().clearGrowthLimit(); } else { // Small heap, clamp to the current growth limit and let the heap release // pages after the growth limit to the non growth limit capacity. b/18387825 dalvik.system.VMRuntime.getRuntime().clampGrowthLimit(); }判断application的标记位是否需要高耗内存,如果是需要,则清除虚拟机对内存增长上限的限制。
8.最重要的部分来了,生成Application对象。
Application app = data.info.makeApplication(data.restrictedBackupMode, null);info为LoadedApk类。这个方法我们具体看一下。
8.1.获取appClass
8.2.获取ClassLoader,getClassLoader方法中,如果不是android系统的package,则去先加载apk的dex文件,然后在返回classLoader.
否则直接返回SystemClassLoader。
mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip, lib,mBaseClassLoader);
这里最终返回的是PathClassLoader对象。
ApplicationLoaders中存在一个ArrayMap mLoaders,一个appir和mSplitAppDirs共同作为key对应一个classLoader,其实就是一个application下的apk文件对应一个classLoader。
8.3.如果manifest文件中设置shareUserid或者设置了已经存在的进程名,那么会共享一个classLoader,
这个classLoader为WarningContextClassLoader();返回的都是parentClassLoader。
8.4.再次创建ContextImpl,作为参数传入newApplication的方法中,成为application的context。反射生成application。
8.5.mActivityThread.mAllApplications.add(app);
8.6.重新给apks中的assets资源文件赋值。
有点乱,第二遍看这些代码的时候再处理。