开始
在之前的文章Activity的启动过程分析中,我们详细分析了act的启动流程,只是后面的第5步当时碍于篇幅原因无法细说,所以这里单独拿出来详细分析下。
示例代码如下:
Intent intent = new Intent(this, TargetAct.class);
startActivity(intent);
每个Android开发都知道当我们写下这样的代码时,系统最终会为我们创建一个TargetAct
的实例,并展现在我们面前,整体流程可以参看下之前的那篇文章,这里我们只分析最终走到的ActivityThread.handleLaunchActivity
方法。
handleLaunchActivity做了哪些事情
- 初始化
WindowManagerGlobal
- 调用performLaunchActivity方法;
- 如果第2步执行ok的话,调用handleResumeActivity,否则会调用AMS的
finishActivity
方法来结束这个act。
performLaunchActivity做了哪些事情
- 从ActivityClientRecord中得到接下来要启动act的ComponentName信息;
- 通过Instrumentation.newActivity方法,利用LoadedApk的类加载器尝试创建act的对象;className字符串就是上面第1步ComponentName里的值;
- 通过LoadedApk(r.packageInfo字段).makeApplication方法尝试创建Application对象,在这个方法里会通过
Class.newInstance()
方法创建Application的对象,并且它的attach、onCreate方法也是在此时被调用的。另外注意下这个方法一进去就有个判断,代码如下:
if (mApplication != null) {
return mApplication;
}
也就是说,只是在第一次当mApplication是null的情况下,才会新创建Application对象,否则这个方法只是返回之前创建好的对象并不会多次创建。也就是说一般情况下Application.onCreate()
之类的方法会被调用一次。这里其实有个疑问,各位可以想想Application.onCreate()
方法会被调用多次吗,如果会那么是在何种情况下呢?
- 为act创建ContextImpl的对象,调用
Activity.attach
方法;
源码如下:
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor) {
attachBaseContext(context);
mFragments.attachHost(null /*parent*/);
mWindow = new PhoneWindow(this);
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
mWindow.setSoftInputMode(info.softInputMode);
}
if (info.uiOptions != 0) {
mWindow.setUiOptions(info.uiOptions);
}
mUiThread = Thread.currentThread();
mMainThread = aThread;
mInstrumentation = instr;
mToken = token;
mIdent = ident;
mApplication = application;
mIntent = intent;
mReferrer = referrer;
mComponent = intent.getComponent();
mActivityInfo = info;
mTitle = title;
mParent = parent;
mEmbeddedID = id;
mLastNonConfigurationInstances = lastNonConfigurationInstances;
if (voiceInteractor != null) {
if (lastNonConfigurationInstances != null) {
mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
} else {
mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
Looper.myLooper());
}
}
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
if (mParent != null) {
mWindow.setContainer(mParent.getWindow());
}
mWindowManager = mWindow.getWindowManager();
mCurrentConfig = config;
}
可以看到此方法完成Activity内部很多重要字段的初始化,特别是mWindow、mWindowManager等字段;
- 调用
Activity.setTheme
方法,如果act申明时指定了theme的话; - 调用
Act.onCreate()
方法,然后是onStart()
方法,如果之前有保存的状态那么还会调用onRestoreInstanceState()
方法,最后调用onPostCreate()
方法,至此整个launch过程算是结束了。
handleResumeActivity方法做了哪些事情
- 如果需要,调用
Act.onNewIntent()
方法; - 如果需要,调用
Act.onActivityResult()
方法; - 调用act的onRestart、onStart、onResume方法,可以参看
Act.performResume()
方法源码; - 将act的DecorView添加到WindowManagerGlobal中,代码如下:
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
wm.addView(decor, l);
}
// If the window has already been added, but during resume
// we started another activity, then don't yet make the
// window visible.
} else if (!willBeVisible) {
if (localLOGV) Slog.v(TAG, "Launch " + r + " mStartedActivity set");
r.hideForNow = true;
}
- 调用
Act.makeVisible()
方法,这样act的界面才能显示在用户面前,代码如下:
void makeVisible() {
if (!mWindowAdded) {
ViewManager wm = getWindowManager();
wm.addView(mDecor, getWindow().getAttributes());
mWindowAdded = true;
}
// 注意这个调用,正是因为它用户才能看到act的界面内容
mDecor.setVisibility(View.VISIBLE);
}
至此,act就已经展现在用户面前,并且处于resume状态,正等待和用户交互了。