Android Activity 圖形化生成簡讀

不知道標題是否準確,即使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的窗體全部顯示出來了.


























 









發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章