前面几篇文章讲述了 activity在远端的创建过程,以及 Application process的创建过程。
现在接着看 activity在本地进程里面的创建流程。
上面的代码里面
在一切条件都准备完成之后,会在
ProcessRecord 里面找到 相应App 进程的远程调用thread,通过ipc 调用到
app.thread.scheduleLaunchActivity()。
执行到ActivityThread中的
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//先跳过GC。。。保证Activity顺利的创建出来
unscheduleGcIdler();
//设置出bitmap的DefaultDensity,Resources的config,DisplayMetrics 等config。
handleConfigurationChanged(null, null);
if (localLOGV) Slog.v(
TAG, "Handling launch of " + r);
// 获取到远端的windowmanager,以便于设置window的animation等属性
WindowManagerGlobal.initialize();
//这个才是重点
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
//这个就是Activity 的resume的事件来源。
//需要注意的是,fragementManager 先接受到resume事件,再是activity。
//深坑
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed);
//后面的基本上就不用看了
}
接着看 performLaunchActivity()
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
//略过,基本上都是在new一些基本的元素
Activity activity = null;
try {
//Activity 是通过系统给的classloader new 出来的。这里应该可以通过反射 去更改本地的classloader。嘿嘿,可以干一些黑科技
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
//奇怪的地方在于,activity居然是比application先new 出来,但是一定不代表着 Activity oncreate的回调是在Application的前面啊
try {
//makeApplication 的时候,先会根据你的 apk的位置 new出一个属于自己App的 PathClassLoader,每次加载的class文件的时候,都会去
//自己的path 找属于自己的dex文件,加载相对于的class类
//然后会根据 自己的ActivityThread 和 LoadedApk data去创建一个ContextImpl,这个应该就是我们常用的ApplicationContext
//并将ApplicationContentResolver,Resources 等资源类也初始化出来
//然后就会先吊用Application中的attch 方法,将上面创建的ContextImpl 倒入到application里面来。
//然后在会吊用 application的 oncreate的方法
//在载入 apk中的R资源文件
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
if (localLOGV) Slog.v(
TAG, r + ": app=" + app
+ ", appName=" + app.getPackageName()
+ ", pkg=" + r.packageInfo.getPackageName()
+ ", comp=" + r.intent.getComponent().toShortString()
+ ", dir=" + r.packageInfo.getAppDir());
if (activity != null) {
//根据activity 在windowmanager中中注册得到的windowtoken 去创建一个带有windowtoken的 context,和上面的区别在于
//是否有权限在window层面显示,接受windowmanager的管理
Context appContext = createBaseContextForActivity(r, activity);
//然后就是将basecontext attach上去,并且新建一个新的window。
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor);
//在吊用oncreate之前就已经将theme属性设置了,如果重载了此方法,是不是意味在 oncreate之前能接收到回调?
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
//终于看到了 activity oncreate的回调了,太晚了
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onCreate()");
}
r.activity = activity;
r.stopped = true;
//然后就是顺序执行 onstart()。
//在performStart()的时候,就会给 decorView设置listener,当画完第一贞之后,就要开始做动画,让activity做动画出来了
if (!r.activity.mFinished) {
activity.performStart();
r.stopped = false;
}
if (!r.activity.mFinished) {
if (r.isPersistable()) {
if (r.state != null || r.persistentState != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
r.persistentState);
}
} else if (r.state != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
}
}
if (!r.activity.mFinished) {
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnPostCreate(activity, r.state,
r.persistentState);
} else {
mInstrumentation.callActivityOnPostCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onPostCreate()");
}
}
}
r.paused = true;
mActivities.put(r.token, r);
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to start activity " + component
+ ": " + e.toString(), e);
}
}
return activity;
}
基本上到这里acitivty 就已经启动并通过windowmanager 动画吊起来啦