1.每個窗口都對應(yīng)一個Activity對象,所以創(chuàng)建應(yīng)用窗口首先是創(chuàng)建Activity.而啟動Activity的任務(wù)由ActivityThread完成,本質(zhì)是構(gòu)造一個Activity對象.當(dāng)ActivityThread接受到Ams發(fā)送的啟動Activity通知時,會創(chuàng)建指定的Activity對象,Activity創(chuàng)建PhoneWindow類--DecorView類--創(chuàng)建相應(yīng)的View或ViewGroup.創(chuàng)建完成后,Activity把創(chuàng)建好的界面顯示到屏幕上,于是調(diào)用WindowManager類,WindowManager創(chuàng)建ViewRoot類和ViewRoot的內(nèi)部類W.之后WindowManager在調(diào)用Wms提供的遠(yuǎn)程接口完成窗口的添加并顯示在屏幕上
- 代碼入口是ActivityThread.performLaunchActivity
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;
Activity activity = null;
try { //1.創(chuàng)建activity的對象,用classLoader從程序中裝載指定Activity對應(yīng)的Class文件
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
}
//2.創(chuàng)建 系統(tǒng)application,appContext appContext本質(zhì)是ContextImpl
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
Context appContext = createBaseContextForActivity(r, activity);
//3.為activity 配置內(nèi)部變量.同時創(chuàng)建Window對象. this變量使Activity對象持有ActivityThread的引用.r 是ActivityClientRecord對象.
r.token是一個Binder,是Ams中的一個HistoryRecord對象. r.parent是一個父Activity,這種理念是為了允許把Activity嵌入到另一個Activity內(nèi)部執(zhí)行,
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.voiceInteractor);
int theme = r.activityInfo.getThemeResource(); //activity使用的主題
if (theme != 0) {
activity.setTheme(theme);
}
//4 這里會調(diào)用Activity的onCreate方法.
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
//調(diào)用 onstart
if (!r.activity.mFinished) {
activity.performStart();
r.stopped = false;
}
//調(diào)用 onRestoreInstanceState
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);
}
}
//調(diào)用 onPostCreate
if (!r.activity.mFinished) {
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnPostCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnPostCreate(activity, r.state);
}
}
}
//ArrayMap<IBinder, ActivityClientRecord>結(jié)構(gòu)
mActivities.put(r.token, r);
return activity;
}
//2.接著看步驟1.3的Actdivity 的attacth方法
//Activity 類
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, IVoiceInteractor voiceInteractor) {
attachBaseContext(context); //新建的contextImpl賦值給mBase.
//1.創(chuàng)建Window.其實是創(chuàng)建了Window的子類PhoneWindow
mWindow = PolicyManager.makeNewWindow(this);
mWindow.setCallback(this); //表示Activity實現(xiàn)的Window的所有回調(diào)函數(shù)
//activity配置重要變量
mUiThread = Thread.currentThread();
mMainThread = aThread;
mInstrumentation = instr;
mToken = token; //Binder HistoryRecord類
mApplication = application;
mIntent = intent;
mComponent = intent.getComponent();
mActivityInfo = info;
mTitle = title;
mParent = parent; //activity
//2.給每個window分配WindowManager,其實是WindowManagerImpl.每個Window都對應(yīng)一個WindowManagerImpl對象,
但WindowManger是一個重量級的類.他的真正實現(xiàn)是WindowManagerGlobal,而WindowManagerImpl只是一個裝飾類,只是
把功能交給WindowManagerGlobal來實現(xiàn)
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
if (mParent != null) {//如果有父activity,就把父acitivty的window賦值給本Activity的window的container變量.
mWindow.setContainer(mParent.getWindow());
}
//activity 也持有WindowManager變量
mWindowManager = mWindow.getWindowManager();
}
//3.接下來是步驟1.4的 mInstrumentation.callActivityOnCreate(activity, r.state);
//1.Instrumentation類 他又調(diào)用Activity的performCreate方法
public void callActivityOnCreate(Activity activity, Bundle icicle) {
prePerformCreate(activity);
activity.performCreate(icicle);
postPerformCreate(activity);
}
//2.Activity 類 此時走到了onCreate ,我們會在onCreate中調(diào)用setContentView方法.接著看
final void performCreate(Bundle icicle) {
onCreate(icicle);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
//3.主要還是調(diào)用 getWindow().setContentView().而 getWindow()就是我們第一步生的Window類PhoneWindow對象.
public void setContentView(View view, ViewGroup.LayoutParams params) {
getWindow().setContentView(view, params);
initWindowDecorActionBar();
}
//4.phoneWindow類
@Override
public void setContentView(View view, ViewGroup.LayoutParams params) {
if (mContentParent == null) {
installDecor(); //5.初始化Decor,為Window創(chuàng)建界面.
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
}
//6.把要添加的view放在 mContentParent中.下邊一個是有位移的添加方法,一個是直接添加.
mContentParnet其實就是我們setcontView是的那個view.他的id就是R.id.content.
我們平時定義的lauout.xml就成了mContentParnet 的子View
if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
view.setLayoutParams(params);
final Scene newScene = new Scene(mContentParent, view);
transitionTo(newScene);
} else {
mContentParent.addView(view, params);
}
//7.此時的callback就是2.1時創(chuàng)建Window時設(shè)置的回調(diào).既Activity自己.
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged(); //調(diào)用activity的onContentChanged回調(diào)方法.
}
}
//4.看3.5的installDecor()方法
private void installDecor() {
if (mDecor == null) {
mDecor = generateDecor(); //1.創(chuàng)建一個DecorView.繼承自FrameLayout,是窗口的最頂層View.
}
if (mContentParent == null) {
//2.這是我們自定義View的父View.
mContentParent = generateLayout(mDecor);
}
// Set up decor part of UI to ignore fitsSystemWindows if appropriate.
mDecor.makeOptionalFitsSystemWindows();//設(shè)置view適配系統(tǒng)窗口
//下邊是根據(jù)設(shè)定的主題來設(shè)置標(biāo)題欄樣式.先不關(guān)注
...
}
//5.接著看 generateLayout()方法.
protected ViewGroup generateLayout(DecorView decor) {//decor是剛創(chuàng)建的DecorView
TypedArray a = getWindowStyle(); //1.指定Window樣式
//2.requestFeature()啟用窗體的擴(kuò)展特性,用戶可調(diào)用這個方法更改window樣式
if (a.getBoolean(R.styleable.Window_windowNoTitle, false)) {
requestFeature(FEATURE_NO_TITLE);
} else if (a.getBoolean(R.styleable.Window_windowActionBar, false)) {
// Don't allow an action bar if there is no title.
requestFeature(FEATURE_ACTION_BAR);
}
...
//3.得到最終要使用的resource文件id.這個文件肯定包含一個id=content的FrameLayout,
int layoutResource;
int features = getLocalFeatures();
mDecor.startChanging();
//4.把該resource文件添加到Decorview里.它是DevorView的唯一view,同時賦值給變量mContentRoot
View in = mLayoutInflater.inflate(layoutResource, null);
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
mContentRoot = (ViewGroup) in;
//5.contentParent是mContentRoot的子view
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
if (contentParent == null) {
throw new RuntimeException("Window couldn't find content container view");
}
mDecor.finishChanging();
return contentParent;
}
//6.這樣.window的窗口元素就設(shè)置完成,接下來通知Wms創(chuàng)建窗口.首先是Activity通知Ams,Ams處理完后調(diào)用Activity的makeVisible()方法,該方法和后續(xù)操作將把窗口真正添加進(jìn)Wms中.
//Activity類
void makeVisible() {
if (!mWindowAdded) {
ViewManager wm = getWindowManager();//1.這里就是Activity內(nèi)部的WindowManager類,具體其實是
WindowManagerImpl類,然后會調(diào)用WindowManagerGlobal的addView方法.
wm.addView(mDecor, getWindow().getAttributes());
mWindowAdded = true;
}
mDecor.setVisibility(View.VISIBLE);
}
//2.接著看WindowManagerGlobal的addView
//1.WindowMangerGlobal有三個變量.ArrayList<View> mViews 每個View都將成為Wms所認(rèn)為的一個窗口.
ArrayList<ViewRootImpl> mRoots 每個View都對應(yīng)的一個ViewRootImpl對象,
ArrayList<WindowManager.LayoutParams> mParams 每個View對應(yīng)的參數(shù),
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;
ViewRootImpl root;
View panelParentView = null;
synchronized (mLock) {
// Start watching for system property changes.
if (mSystemPropertyUpdater == null) {
mSystemPropertyUpdater = new Runnable() {
@Override public void run() {
synchronized (mLock) {
for (int i = mRoots.size() - 1; i >= 0; --i) {
mRoots.get(i).loadSystemProperties(); //加載系統(tǒng)屬性
}
}
}
};
SystemProperties.addChangeCallback(mSystemPropertyUpdater);
}
int index = findViewLocked(view, false); //2.如果該View已經(jīng)添加過了.就不允許重復(fù)添加
if (index >= 0) {
if (mDyingViews.contains(view)) {
// Don't wait for MSG_DIE to make it's way through root's queue.
mRoots.get(index).doDie();
} else {
throw new IllegalStateException("View " + view
+ " has already been added to the window manager.");
}
// The previous removeView() had not completed executing. Now it has.
}
// If this is a panel window, then find the window it is being
// attached to for future reference.
if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
//3.1000-1999之間,是子窗口,需要找他的父窗口保存在panelParentView變量中
final int count = mViews.size();
for (int i = 0; i < count; i++) {
if (mRoots.get(i).mWindow.asBinder() == wparams.token) {
panelParentView = mViews.get(i);
}
}
}
//4.生成ViewRootImpl.用來溝通Wms和View,
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
//5.把該view對應(yīng)的變量添加到WindowManagerGlobal的三個對象中.
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
}
// do this last because it fires off messages to start doing things
try {
//6.完成最后的真正意義的添加動作 view是要添加的窗口 wParams是窗口的參數(shù)LayoutParams,panelParentView表示該窗口的父窗口,可以為空
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
throw e;
}
}
//接下來看ViewRootImpl的setView方法
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
if (mView == null) {
mView = view;
//1.賦值attrs
mWindowAttributes.copyFrom(attrs);
if (mWindowAttributes.packageName == null) {
mWindowAttributes.packageName = mBasePackageName;
}
attrs = mWindowAttributes;
//2.配置參數(shù)
mSoftInputMode = attrs.softInputMode;
mWindowAttributesChanged = true;
mWindowAttributesChangesFlag = WindowManager.LayoutParams.EVERYTHING_CHANGED;
mAttachInfo.mRootView = view;
mAttachInfo.mScalingRequired = mTranslator != null;
mAttachInfo.mApplicationScale =
mTranslator == null ? 1.0f : mTranslator.applicationScale;
//3.如果有父窗口,把父窗口的token賦值給mAttachInfo
if (panelParentView != null) {
mAttachInfo.mPanelParentWindowToken
= panelParentView.getApplicationWindowToken();
}
mAdded = true;
int res; /* = WindowManagerImpl.ADD_OKAY; */
// Schedule the first layout -before- adding to the window
// manager, to make sure we do the relayout before receiving
// any other events from the system.
//4.發(fā)出重繪請求,僅是發(fā)出一個異步請求,使Ui線程的下一個消息處理是界面重繪,使窗口在相應(yīng)其他消息之前
先變得可見
requestLayout();
try { //5.通知Wms添加窗口,mWindowSession是WindowManagerGlobla的一個鏡頭變量,每個應(yīng)用程序僅有一個mWindowSession對象,類型為IWindowSession,是一個Binder引用,對應(yīng)Wms中的Session子類,Wms為每個應(yīng)用程序分配一個Session對象.
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mInputChannel);
} catch (RemoteException {
throw new RuntimeException("Adding window failed", e);
}
}
至此,窗口的創(chuàng)建過程全部結(jié)束.
最后總結(jié)一下.第一步.是在ActivityThread的performLaunchActivity方法通過反射創(chuàng)建Activity啟動的對象,同時為Activity創(chuàng)建添加一個ContextImpl對象,調(diào)用Activity.attach方法,然后執(zhí)行Activity的onCreate,onStart.第二步Activity.attach中,為該Acitivity創(chuàng)建一個PhoneWindow(繼承自Window)對象,這是一個輕量的對象,其實內(nèi)部是由WindowManagerGlobal實現(xiàn)具體操作.第三步.在執(zhí)行Activity的onCreate過程中,為activity創(chuàng)建DecorView,這是每個activity的頂層view.他里邊包含一個id為content的view.就是我們調(diào)用setContentView的父view,第四部,Activity的view設(shè)置完成后.Activity通知Ams,Ams處理完后調(diào)用Activity的makeVisible()方法,該方法和后續(xù)操作將把窗口真正添加進(jìn)Wms中.此時wms為創(chuàng)建一個ViewRootImpl類,用來溝通wms和view.最后.ViewRootImpl在把view進(jìn)行一些處理后,通知Wms添加窗口