activity setContentView 解析

来源:互联网 发布:阿里域名隐私保护 编辑:程序博客网 时间:2024/06/05 08:58
基于 android 4.4 src:
Activity 的 setContentView():
public void setContentView(View view, ViewGroup.LayoutParams params) {
        getWindow().setContentView(view, params);
        initActionBar();
}

首先做的是将Avticity绑定的phoneWindow(通过getWindow())将inflate出来的view set为phoneWindow的view.
然后才是初始化系统的actionBar.

PhoneWindow.java
@Override
    public void setContentView(View view, ViewGroup.LayoutParams params) {
        if (mContentParent == null) {
            installDecor(); 如果PhoneWindow里面的DecorView的mContentParent还没有被install上,那么就install
        } else {
            mContentParent.removeAllViews(); 如果之前已经有mContentParent了,那么将mContentParent里的所有view清空
        }
        mContentParent.addView(view, params); 将要set 的 view加入到decorView里的mContentParent中
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }
    }


DecorView本质就是一个FrameLayout
private final class DecorView extends FrameLayout implements RootViewSurfaceTaker

install DecorView到phoneWindow的过程
private void installDecor() {
        if (mDecor == null) {
            mDecor = generateDecor();
        很简单,return new DecorView(getContext(), -1);
            /** The feature ID of the panel, or -1 if this is the application's DecorView */
            mFeatureId 是 -1

            mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
            mDecor.setIsRootNamespace(true);
            if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
                mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
            }
        }
        if (mContentParent == null) {
            mContentParent = generateLayout(mDecor);
            generateLayout()会设置一堆的flag到window,
        然后会从 layout.screen_simple_overlay_action_mode / layout.screen_simple中选择一个进行inflate,
            然后加入到decorView中,
            而后,调用ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
            其中ID_ANDROID_CONTENT = com.android.internal.R.id.content
            而window的findViewById()其实是getDecorView().findViewById(id),因此
            contentParent代表其实就是刚才加入到decorView中的layout中的一个view,及decorView包含了一个view,
            该view又包含contentParent, 而contentParent就是mContentParent, acticity setContainerView()所
            set的view就是被加入到了这个mContentParent中。

            // Set up decor part of UI to ignore fitsSystemWindows if appropriate.
            mDecor.makeOptionalFitsSystemWindows();

            先面的是将tilte设置到mDecor中的title view中,以及设置actionBar
            ........................................

                    // Post the panel invalidate for later; avoid application onCreateOptionsMenu
                    // being called in the middle of onCreate or similar.
                    mDecor.post(new Runnable() {
                        public void run() {
                            // Invalidate if the panel menu hasn't been created before this.
                            PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
                            if (!isDestroyed() && (st == null || st.menu == null)) {
                                invalidatePanelMenu(FEATURE_ACTION_BAR);
                            }
                        }
                    });

                    View的post方法:Causes the Runnable to be added to the message queue.
                 * The runnable will be run on the user interface thread
        public boolean post(Runnable action) {
                final AttachInfo attachInfo = mAttachInfo;
                if (attachInfo != null) {
                        return attachInfo.mHandler.post(action);
                }
                // Assume that post will succeed later
                ViewRootImpl.getRunQueue().post(action);
                return true;
            }

                }
            }
        }
    }
0 0
原创粉丝点击