参考书籍:<Android 系统源代码情景分析 第3版>
看书时,好些书都会提到Activity中的makeVisible(),这个方法会用到mDecor变量,但是很少有说这个变量何时赋值的.
- AMS发出启动
Activity
// ActivityStack.java
public class ActivityStack {
final boolean realStartActivityLocked(ActivityRecord r,ProcessRecord app, boolean andResume, boolean checkConfig)throws RemoteException {
...
try {
...
// app.thread 是ActivityThread.ApplicationThread 它是一个Binder本地对象.
// 这里就从AMS切换到应用APP进程中了.
app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
System.identityHashCode(r),
r.info, r.icicle, results, newIntents, !andResume,
mService.isNextTransitionForward());
...
} catch (RemoteException e) {
...
}
...
return true;
}
}
// 启动Activity
// ActivityThread.ApplicationThread.java
public final class ActivityThread {
private final class ApplicationThread extends ApplicationThreadNative {
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,t,ActivityInfo info, Bundle state, List<ResultInfo> pendingResults,List<Intent> pendingNewIntents, boolean notResumed, boolean isForward) {
// 创建一个目标ActivityClientRecord对象
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
r.activityInfo = info;
r.state = state;
r.pendingResults = pendingResults;
r.pendingIntents = pendingNewIntents;
r.startsNotResumed = notResumed;
r.isForward = isForward;
// TODO 第一
queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
}
}
// TODO 第一
private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
synchronized (this) {
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
// TODO 第二
mH.sendMessage(msg);
}
}
private final class H extends Handler {
// TODO 第二
public void handleMessage(Message msg) {
switch (msg.what) {
case LAUNCH_ACTIVITY: {
// 取出刚刚在ApplicationThread.scheduleLaunchActivity中创建的ActivityClientRecord对象
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
r.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo);
// TODO 第三
handleLaunchActivity(r, null);
}
break;
}
}
}
// TODO 第三
private final void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// TODO 第四
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
// TODO 第五
// 第四步中,创建好了目标Activity,WindowPhone,mDecorView.
handleResumeActivity(r.token, false, r.isForward);
...
} else {
...
}
}
// TODO 第四
private final Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
Activity activity = null;
try {
// 通过类加载器创建 Activity对象
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
r.intent.setExtrasClassLoader(cl);
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
...
}
try {
// 创建 Application 对象
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
...
if (activity != null) {
ContextImpl appContext = new ContextImpl();
appContext.init(r.packageInfo, r.token, this);
appContext.setOuterContext(activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mConfiguration);
...
// 执行Activity中attach()方法,attach()中会创建Activity的PhoneWindow和WindowManagerImpl等对象
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstance,
r.lastNonConfigurationChildInstances, config);
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstance = null;
r.lastNonConfigurationChildInstances = null;
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
// 这里最终会调用到经常用到的Activity中的onCreate().
// onCreate()最终会创建一个mDecorView对象, 我们一般使用的布局文件就是被加入到mDecorView的子布局系统文件的id为content的ViewGroup中.
mInstrumentation.callActivityOnCreate(activity, r.state);
...
r.activity = activity;
r.stopped = true;
...
}
r.paused = true;
// mActivities对象的类型 HashMap<IBinder, ActivityClientRecord>.
// 它作用是ActivityClientRecord与token值一一对应记录起来.
mActivities.put(r.token, r);
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
...
}
return activity;
}
// TODO 第五
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
...
// performResumeActivity最终执行下去会调用Activity中我们非常熟悉的,调用链如下:
// performResumeActivity
// Activity.performResume()
// Instrumentation.callActivityOnResume()
// Activity.onResume()
ActivityClientRecord r = performResumeActivity(token, clearHide);
if (r != null) {
final Activity a = r.activity;
...
if (r.window == null && !a.mFinished && willBeVisible) {
// 从目标Actity中获取PhoneWindow对象
r.window = r.activity.getWindow();
// 获取PhoneWindow中的mDecorView对象
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
// 将mDecorView对象赋值给Activity中的mDecor变量,到这里就知道了Activity中的mDecor何时被赋值的了.
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
// 这个变量按照字面意思是窗口是否添加decor,但decorView就是在PhoneWindow中创建的,
// 这个变量的表示是decorView是否展示.
a.mWindowAdded = true;
// addView最终会调用到ViewRoot.setView(),随后的逻辑就在WMS中了.
// 这里就是开始展示decorView了, 很多文章说这里是添加decorView.
wm.addView(decor, l);
}
} else if (!willBeVisible) {
}
} else {
}
if (r.activity.mVisibleFromClient) {
// makeVisible()里面也会执行wm.addView();
// 但是有个前提条件mWindowAdded变量为false.
// 所以WindowManager不会重复对decor进行添加展示.
r.activity.makeVisible();
}
}
}