不知道標題是否準確,即使Activity開始自己的週期,從attach開始,接着第一篇的attach點.多說一句,前面跟隨思路,一步一步的打log,生成services.jar放到系統裏面運行,就知道自己的判定是否正確了.
下面回到Activity的類,attach :
final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token,
Application application, Intent intent, ActivityInfo info, CharSequence title,
Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances,
Configuration config) {
attach(context, aThread, instr, token, 0, application, intent, info, title, parent, id,
lastNonConfigurationInstances, config);
}
新建和初始化窗口:
mWindow = PolicyManager.makeNewWindow(this);
mWindow.setCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
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();
mWindow是Window的一個對象,但是Window本身是一個抽象類,新建一個窗體:
mWindow = PolicyManager.makeNewWindow(this);
這個開始.由PolicyManager開始:
// The static methods to spawn new policy-specific objects
public static Window makeNewWindow(Context context) {
return sPolicy.makeNewWindow(context);
}
而sPolicy是IPolicy.它是一個接口類:
/* The implementation of this interface must be called Policy and contained
* within the com.android.internal.policy.impl package */
public interface IPolicy {
public Window makeNewWindow(Context context);
public LayoutInflater makeNewLayoutInflater(Context context);
public WindowManagerPolicy makeNewWindowManager();
public FallbackEventHandler makeNewFallbackEventHandler(Context context);
}
實現類Policy :
public Window makeNewWindow(Context context) {
return new PhoneWindow(context);
}
返回了一個PhoneWindow對象.
public PhoneWindow(Context context) {
super(context);
mLayoutInflater = LayoutInflater.from(context);
}
獲取的這個返回對象.
... ...
在進入Activity的onCreate方法:
在這個地方首先看一下下面三張圖:
下面是視圖的框架流程:
視窗體的組成分佈:
下面的是setContentView的地位:
設置佈局或者View時,最後進入PhoneWindow類:
@Override
public void setContentView(View view, ViewGroup.LayoutParams params) {
if (mContentParent == null) {
installDecor();
} else {
mContentParent.removeAllViews();
}
mContentParent.addView(view, params);
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
}
如果不是子View,即Activity父容器未創建,則先創建Activity父容器,那麼程序就會運行installDecor()方法:
private void installDecor() {
if (mDecor == null) {
mDecor = generateDecor();
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
}
if (mContentParent == null) {
mContentParent = generateLayout(mDecor);
通過generateDecor產生一個mDecor對象:
protected DecorView generateDecor() {
return new DecorView(getContext(), -1);
}
下面:
private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {
/* package */int mDefaultOpacity = PixelFormat.OPAQUE;
/** The feature ID of the panel, or -1 if this is the application's DecorView */
private final int mFeatureId;
private final Rect mDrawingBounds = new Rect();
private final Rect mBackgroundPadding = new Rect();
private final Rect mFramePadding = new Rect();
private final Rect mFrameOffsets = new Rect();
private boolean mChanging;
private Drawable mMenuBackground;
private boolean mWatchingForMenu;
private int mDownY;
private ActionMode mActionMode;
private ActionBarContextView mActionModeView;
private PopupWindow mActionModePopup;
private Runnable mShowActionModePopup;
public DecorView(Context context, int featureId) {
super(context);
mFeatureId = featureId;
}
這個DecorView是一個繼承了FrameLayout的視圖類.這裏面記住featureId,創建以後:
if (mContentParent == null) {
mContentParent = generateLayout(mDecor);
// Set up decor part of UI to ignore fitsSystemWindows if appropriate.
mDecor.makeOptionalFitsSystemWindows();
mTitleView = (TextView)findViewById(com.android.internal.R.id.title);
if (mTitleView != null) {
mTitleView.setLayoutDirection(mDecor.getLayoutDirection());
if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
開始創建跟View,其中所有自定義View的根View, id="@android:id/content",下面:
protected ViewGroup generateLayout(DecorView decor) {
// Apply data from current theme.
TypedArray a = getWindowStyle(); ... ...
int features = getLocalFeatures();
// System.out.println("Features: 0x" + Integer.toHexString(features));
if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
if (mIsFloating) {
TypedValue res = new TypedValue();
getContext().getTheme().resolveAttribute(... ...
這個方法很有意思,一看就知道我們平時設置Activity主題theme,SDK之類的信息是如何處理的了,開始加載設置這個窗體的風格樣式(根據指定的theme和feature).
添加視窗:
View in = mLayoutInflater.inflate(layoutResource, null);
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
由窗口頂層視窗decor添加Activity佈局各個View.
這個方法可以仔細閱讀,不過注意它的返回值是,mContentParent.這樣整個窗體框架基本出來了.由於程序app提供的是xml,那麼就需要解析並且返回view,通過下面:
View in = mLayoutInflater.inflate(layoutResource, null);
通過它解析xml,獲取信息:
public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {
synchronized (mConstructorArgs) {
final AttributeSet attrs = Xml.asAttributeSet(parser);
Context lastContext = (Context)mConstructorArgs[0];
mConstructorArgs[0] = mContext;
View result = root;
基本的視窗就差不多了.
1> : 創建一個DecorView對象,該對象將作爲整個應用窗口的根視圖
2> : 創建不同的窗口修飾佈局文件,並且獲取Activity的佈局文件該存放的地方,由該窗口修飾佈局文件內id爲content的FrameLayout指定 。
3> : 將Activity的佈局文件添加至id爲content的FrameLayout內
看過Activity週期的都會知道,Activity窗體顯示出來並不是在oncreate時候,而是onResume的時候:回到ActivityManagerService類,回調onResume中:
//系統resume一個Activity時,調用此方法
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
ActivityRecord r = performResumeActivity(token, clearHide);
//...
if (r.activity.mVisibleFromClient) {
r.activity.makeVisible();
}
}
然後進入Activity類:
void makeVisible() {
if (!mWindowAdded) {
ViewManager wm = getWindowManager();
wm.addView(mDecor, getWindow().getAttributes());
mWindowAdded = true;
}
mDecor.setVisibility(View.VISIBLE);
}
這個時候整個Activity的窗體全部顯示出來了.