A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

咱们既然是要分析这三者的关系,首先我们应该要找到着手点。
这个点其实就在咱们最长用activity里开始入手,咱们都知道activity里有个方法setContentView方法。所以咱们就从这里开始入手吧~




### Activity.java

            public void setContentView(View view) {
                getWindow().setContentView(view);
            }


getWindow对应的为Window对象,而window对象是一个抽象类,要找到window对象在哪里初始化的

    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, String referrer, IVoiceInteractor voiceInteractor) {
                ......

        mWindow = PolicyManager.makeNewWindow(this);
                ......
        }


### PolicyManager.java

    private static final IPolicy sPolicy;

    public static Window makeNewWindow(Context context) {
        return sPolicy.makeNewWindow(context);
    }

### IPolicy.java

    /* 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);
        ...
    }


### Policy.java

    public class Policy implements IPolicy {
        ...
        public PhoneWindow makeNewWindow(Context context) {
            return new PhoneWindow(context);
        }
        ...
    }


由此可知mWindow对象实在activity得attach方法中创建的

实际上setContentView方法是调用PhoneWindow得setContentView方法

### PhoneWindow.java

    @Override
    public void setContentView(View view) {
        setContentView(view, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
    }

    @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) {
            cb.onContentChanged();
        }
    }

会从一个参数的走到2个参数的


installDecor()方法
       
          private void installDecor() {
                if (mDecor == null) {
                    mDecor = generateDecor();
                                .......
                }
                if (mContentParent == null) {
                    mContentParent = generateLayout(mDecor);
                                .......
                        }
        }


其中mDecor是一个DecorView对象,DecorView继承自FrameLayout


generateLayout(mDecor)方法

    protected ViewGroup generateLayout(DecorView decor) {
                ......
        if (a.getBoolean(com.android.internal.R.styleable.Window_windowNoTitle, false)) {
            requestFeature(FEATURE_NO_TITLE);
        }
                ......
        mDecor.startChanging();

        View in = mLayoutInflater.inflate(layoutResource, null);
        decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
                ......
        ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);

                ......
        mDecor.finishChanging();

        return contentParent;
    }

通过上面方法拿到了mContentParent
再次回归setContentView

          @Override
    public void setContentView(View view, ViewGroup.LayoutParams params) {
        if (mContentParent == null) {
            ......
        } else {
            mContentParent.removeAllViews();
        }
        mContentParent.addView(view, params);
                ......
    }

会判断mContentParent是否为空,如果为空说明第一次创建则移除mContentParent里面所有的view,然后再把咱们自己得view对象放进去






3 个回复

倒序浏览

回帖奖励 +1

支持老师,赞!!!
回复 使用道具 举报
千千阙歌 来自手机 中级黑马 2017-3-29 23:30:07
藤椅
看看看看
回复 使用道具 举报
多谢分享
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马