Android开发之setContentView的那些事

原文:

https://blog.csdn.net/nugongahou110/article/details/49662211

setContentView方法位于Window类,实现Window的子类PhoneWindow。
每一个Activity都有一个PhoneWindow

以下为setContentView在PhoneWindow上的实现:

public class PhoneWindow extends Window implements MenuBuilder.Callback {
    //...
    //...
    //...
    //重载方法1
    @Override
    public void setContentView(int layoutResID) {
        if (mContentParent == null) {
            installDecor();
        } else {
            mContentParent.removeAllViews();
        }
        mLayoutInflater.inflate(layoutResID, mContentParent);
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }
    }
    //重载方法2
    @Override
    public void setContentView(View view) {
        setContentView(view, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
    }
    //重载方法3
    @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();
        }
    }

    //...
    //...
    //...
}

代码中可看出当mContentParent不为空时,清除mContentParent中的内容,若为空,则执行initallDecor方法。
以下为initallDecor方法:

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

通过generateLayout方法得到mDecor对象,再将mDecor作为形参执行generateLayout方法
以下为generateDecor方法代码:

protected DecorView generateDecor() {
        return new DecorView(getContext(), -1);
    }

以下为DecorView的结构图
DecorView的结构图

以下为generateLayout(mDecor)方法代码:

protected ViewGroup generateLayout(DecorView decor) {
//...

//省略一些设置Window样式的代码,直接来看我们最关心的代码!
 ViewGroup contentParent =(ViewGroup)findViewById(ID_ANDROID_CONTENT);
                    //...           
                    return contentParent;
                }
         }

ID_ANDROID_CONTENT为R.id.content,就是下图的那个FrameLayout
ID_ANDROID_CONTENT
所以ContentView即为这个FramLayout

重回PhoneWindiow类中对setContentView的实现代码:

public class PhoneWindow extends Window implements MenuBuilder.Callback {
    //...
    //...
    //...
    //重载方法1
    @Override
    public void setContentView(int layoutResID) {
        if (mContentParent == null) {
            installDecor();
        } else {
            mContentParent.removeAllViews();
        }
        mLayoutInflater.inflate(layoutResID, mContentParent);
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }
    }
    //重载方法2
    @Override
    public void setContentView(View view) {
        setContentView(view, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
    }
    //重载方法3
    @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();
        }
    }

    //...
    //...
    //...
}

总结

  首先判断mContentParent是否为空,为空则获取mContentParent,获取mContentParent 需要调用installDecor方法获取DecorView对象,然后通过DecorView对象再获取ContentParentView对象。若不为空,则清除掉mContentParent里的所有View视图。
  接下来通过反射加载到我们传入的布局,接着下面会通过调用getCallBack得到一个CallBack对象cb,其实这个cb就是我们的Activity,接着会调用Activity的onContentChanged方法,这个方法是一个空实现,会在我们调用setContentView方法后调用。

注意:重载方法1是通过反射来传入布局的,而重载方法2和3是通过普通方法载入的,而这两种方法的不同如下文所示

重载方法1使用载入布局的方法是通过R.layout…反射得来的View,所以没次调用setContentView方法拿到的View都是不同的。
而重载方法1和2都是通过直接传View对象过来绑定布局的,所以多次调用setContentView拿到的都是同一个View。

猜你喜欢

转载自blog.csdn.net/figurers/article/details/79691025