Application 分析
Application主要作用:
- 保存应用进程内的全局变量
- 初始化操作,application的创建排在四大组件之前,并且存活的时间长,有多少个进程就有多少个application
- 提供应用上下文
Application 源码分析
- 首次先我们先给出方法调用的大概流程,下面我们要根据这个对Application的生命周期进行简单的分析:
-->ActivityThread.main()
-->ActivityThread.atttach()
-->ActivityManagerService.attachApplication()
-->ActivityManagerService.attachApplicationLocked()
-->ActivityThread.bindApplication()
-->ActivityThread.sendMessage(H.BIND_APPLICATION, data)
-->ActivityThread.handleBindApplication()
-->LoadApk.makeApplication(true, null);
-->Instrumentation.newApplication()
-->mInstrumentation.callApplicationOnCreate(app);==>(app.onCreate())
我们从ActivityThread的入口方法看起,(注意:源代码比较多,下面贴出来的只是摘下来的主要代码,要对照源码具体分析)
public static void main(String[] args) {
...
// 准备好主线程的消息循环
Looper.prepareMainLooper();
....
ActivityThread thread = new ActivityThread();
// 通过attach()函数向AMS打报告
thread.attach(false, startSeq);
...
// 主线程循环开始
Looper.loop();
}
上面主要代码做了什么?主要是准备好主线程的消息循环,然后向AMS打报告,这attach()就是应用程序向AMS报告的,我们接下来看attach()方法做了些什么
private void attach(boolean system, long startSeq) {
...
final IActivityManager mgr = ActivityManager.getService();
try {
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
这里面有Binder调用,在attach()中先 获取AMS的远程代理对象。然后调用ams的attachApplication方法,我们看看在Ams中是怎么处理的:
@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
synchronized (this) {
...
attachApplicationLocked(thread, callingPid, callingUid, startSeq);
Binder.restoreCallingIdentity(origId);
}
}
我们可以看到,attachApplication里面调用了attachApplicationLocked(),
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid, int callingUid, long startSeq) {
...
thread.bindApplication(processName, appInfo,...);
...
}
在这里Binder又绕了一圈,调用应用程序中的binderAppliacation(),这个thread,就是通过传进来的应用进程的ApplicationThread的binder对象,下面我们又回到应用进程,我们看看在应用进程中做了些什么:
public final void bindApplication(String processName,
ApplicationInfo appInfo,...){
...
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.providers = providers;
....
sendMessage(H.BIND_APPLICATION, data);
}
在这里我们看到bindApplication()发送了个消息,其中H继承自Handler,data封装了应用的一些信息。接下来我们看看应用怎么收到消息后怎么处理:
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;
case EXIT_APPLICATION:
...
case RECEIVER:
...
case CREATE_SERVICE:
...
}
处理消息时,首先判断要需要处理的类型是什么,有BIND_APPLICATION,EXIT_APPLICATIO,RECRIVER,CREATE_SERVICE等等,之前我们发送的是H.BIND_APPLICATION。(H是ActivityThread的一个私有内部类,继承了Handler,其作用很简单,与我们平时开发中使用Handler的作用一样,处理消息以及将消息压入队列)接下来我们就看看在handleMessage()里面如何处理:可以看到调用了 handleBindApplication()方法,我们就跳转到handleBindApplication()中,看看到底做了什么:
private void handleBindApplication(AppBindData data) {
...
// 调用getPackageInfoNoCheck()方法获取一个对象,用来安装包信息,
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
...
// makeApplication来创建Application对象
app = data.info.makeApplication(data.restrictedBackupMode, null);
// 调用callApplicationOnCreate,就是就是application的生命周期的回调函数app.onCreate()
mInstrumentation.callApplicationOnCreate(app);
...
}
首先是调用getPackageInfoNoCheck()方法,获取一个对象(loadAkp对象),用来描述安装信息,然后调用其makeApplication()方法,创建一个Application对象,接着调用callApplicationOnCreate()方法,这个方法最后就是回调了application生命周期的onCreate()方法。
接下来,我们看看上面的makeApplication()方法是怎么来创建Application对象的:
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
if (mApplication != null) {
return mApplication;
}
...
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
...
return app;
}
在makeApplication()方法中,一开始就先判断mApplication是否存在,如果存在则直接返回,避免application多次创建。否者就需要创建新的Application对象,在创建新的Application对象前,需要先给它创建一个Context。然后在创建新的Application时传入这个Context.
我们已经找到在哪创建Application对象了,那继续看看他是怎么被创建出来的。接着看:
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;
}
在newApplication()方法中,先通过getFactory()获取一个App的一个工厂类对象,然后调用他的instanceApplication()方法来创建Application对象。现在已经创建好了Application对象,再看看接下来做了什么?接下来调用Application的attach()方法参数还是之前创建的那个context对象,这是干嘛的呢,我们顺着这个attach()方法看看:
final void attach(Context context) {
attachBaseContext(context);
...
}
我们知道Application继承ContextWrapper(ContextWrapper是对Context的封装),这里的attach()里最终将传进来的context赋值给Context的对象mBase,以后对Context其实都是对mBase的操作。
2.到此,我们已经简单的对Application 的初始化流程做了简单的梳理。
从new Application() ---> application.attach(Context) ---> application.onCreate()
这里我们可以看出初始化的先后顺序,Context是在Application构造方法之后设置的,所以不能在Application的构造方法中使用Context做一下初始化的操作。