黑马程序员技术交流社区

标题: 【济南中心】Activity、Window、View之间的关系 [打印本页]

作者: 大山哥哥    时间: 2017-3-27 20:47
标题: 【济南中心】Activity、Window、View之间的关系
咱们既然是要分析这三者的关系,首先我们应该要找到着手点。
这个点其实就在咱们最长用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对象放进去







作者: 橘子哥    时间: 2017-3-28 09:25
支持老师,赞!!!
作者: 千千阙歌    时间: 2017-3-29 23:30
看看看看
作者: baby14    时间: 2019-8-5 07:39
多谢分享




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2