Those things about setContentView in Android development

original:

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

The setContentView method is located in the Window class and implements the Window subclass PhoneWindow.
Every Activity has a PhoneWindow

The following is the implementation of setContentView on 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();
        }
    }

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

It can be seen in the code that when mContentParent is not empty, the content in mContentParent is cleared, and if it is empty, the initallDecor method is executed.
The following is the initallDecor method:

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

Obtain the mDecor object through the generateLayout method, and then execute the generateLayout method with mDecor as a formal parameter.
The following is the generateDecor method code:

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

The following is the structure diagram of DecorView
Structure diagram of DecorView

The following is the code of the generateLayout(mDecor) method:

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

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

ID_ANDROID_CONTENT is R.id.content, which is the FrameLayout in the picture below,
ID_ANDROID_CONTENT
so ContentView is this FramLayout

Return to the implementation code of setContentView in the PhoneWindow class:

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();
        }
    }

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

Summarize

  First determine whether mContentParent is empty, if it is empty, get mContentParent. To get mContentParent, you need to call the installDecor method to get the DecorView object, and then get the ContentParentView object through the DecorView object. If not empty, clear all Views in mContentParent.
  Next, load the layout we passed in through reflection, and then we will get a CallBack object cb by calling getCallBack. In fact, this cb is our Activity, and then we will call the onContentChanged method of Activity. This method is an empty implementation and will be used in our Called after calling the setContentView method.

Note: Overloaded method 1 is passed into the layout through reflection, while overloaded methods 2 and 3 are loaded through ordinary methods, and the differences between the two methods are as follows

Overload method 1 uses the method of loading the layout, which is the View obtained through R.layout... reflection, so the View obtained by calling the setContentView method every time is different.
The overloaded methods 1 and 2 both bind the layout by directly passing the View object, so the same View is obtained by calling setContentView multiple times.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325586435&siteId=291194637
Recommended