android setContentView
来源:互联网 发布:Tensorflow 字符识别 编辑:程序博客网 时间:2024/05/24 01:11
http://blog.csdn.net/yanbober/article/details/46128379
一下是对上面文章的总结
Acitivity的setContentView
public void setContentView(int layoutResID) { getWindow().setContentView(layoutResID); initWindowDecorActionBar(); } public void setContentView(View view) { getWindow().setContentView(view); initWindowDecorActionBar(); } public void setContentView(View view, ViewGroup.LayoutParams params) { getWindow().setContentView(view, params); initWindowDecorActionBar(); }
getwindow返回一个PhoneWindow的对象,该对象关系如下图
Window是一个抽象类,提供了绘制窗口的一组通用API。
PhoneWindow是Window的具体继承实现类。而且该类内部包含了一个DecorView对象,该DectorView对象是所有应用窗口(Activity界面)的根View。
DecorView是PhoneWindow的内部类,是FrameLayout的子类,是对FrameLayout进行功能的修饰(所以叫DecorXXX),是所有应用窗口的根View 。
从上面的源代码我们可以知道都是调用phoneWindow(getWindow函数返回)中的setContentView函数来初始化我们的View,接着我们看phoneWindow类的setContentView源码
setContentView(int layoutResID
public void setContentView(int layoutResID) { // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window // decor, when theme attributes and the like are crystalized. Do not check the feature // before this happens. if (mContentParent == null) { //初始化DecorView installDecor(); } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {//默认false, mContentParent.removeAllViews(); /*mContentParent是什么呢,我们知道DecorView是一个FrameLayout,它是我们的根布局,除此之外我们都知道我们在写android app的时候会设置主题,而这个主题其实是一个布局文件(ViewGroup),这个布局文件中一班都有一个id为content的FramLayout的ViewGroup,mContentParent就是指着它 */ } if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) { final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID, getContext()); transitionTo(newScene); } else { //将资源文件转换为View树树 mLayoutInflater.inflate(layoutResID, mContentParent); //mLayoutInflater是一个LayoutInflater } final Callback cb = getCallback(); if (cb != null && !isDestroyed()) { cb.onContentChanged(); } }
setContentView(View view)
public void setContentView(View view) { setContentView(view, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); }
可以看见setContentView(View view)调用setContentView(View view, ViewGroup.LayoutParams params)
setContentView(View view, ViewGroup.LayoutParams params)
public void setContentView(View view, ViewGroup.LayoutParams params) { // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window // decor, when theme attributes and the like are crystalized. Do not check the feature // before this happens. if (mContentParent == null) { installDecor(); } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) { mContentParent.removeAllViews(); } if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) { view.setLayoutParams(params); final Scene newScene = new Scene(mContentParent, view); transitionTo(newScene); } else { //直接根据位置参数添加View mContentParent.addView(view, params); } final Callback cb = getCallback(); if (cb != null && !isDestroyed()) { cb.onContentChanged(); } }
可以看见和setContentView(int layoutResID)类似,只不过不需要xml,而是直接把view,add进去而已
setContentView中的installDecor()
既然知道初始化DecorView之后setContentView把资源添加进DecorView,那么问题的核心来了,第一次调用setContentView时时怎么初始化DecorView对象的呢?
private void installDecor() { if (mDecor == null) { mDecor = generateDecor(); mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS); mDecor.setIsRootNamespace(true); if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) { mDecor.postOnAnimation(mInvalidatePanelMenuRunnable); } } if (mContentParent == null) { //根据窗口的风格修饰,选择对应的修饰布局文件,并且将id为content的FrameLayout赋值给mContentParent mContentParent = generateLayout(mDecor); //...... //初始化一堆属性值 } }
从上面代码我们可以看出来installDecor干了两件事generateDecor初始化mDecor ,generateLayout(mDecor)初始化mContentParent 。我们一个一个来看
generateDecor
protected DecorView generateDecor() { return new DecorView(getContext(), -1); }
没什么好说的,单纯new了一个DecorView
generateLayout(mDecor)
protected ViewGroup generateLayout(DecorView decor) { // Apply data from current theme.//获得xml设置的样式主题 TypedArray a = getWindowStyle(); //...... //依据主题style设置一堆值进行设置 // Inflate the window decor. int layoutResource; //获得在代码中设置的样式主题 int features = getLocalFeatures(); //...... //根据设定好的features值选择不同的窗口修饰布局文件,得到layoutResource值 //把选中的窗口修饰布局文件添加到DecorView对象里,并且指定contentParent值 View in = mLayoutInflater.inflate(layoutResource, null); //这个in中包含了我们我们选中的主题样式,然后帮in添加到decor中(DecorView) decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); mContentRoot = (ViewGroup) in; ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT); //这里的findViewById(ID_ANDROID_CONTENT)其实就是就是主题中id为content的FramLayout if (contentParent == null) { throw new RuntimeException("Window couldn't find content container view"); } //...... //继续一堆属性设置,完事返回contentParent return contentParent; }
所以installDecor方法实质就是产生mDecor和mContentParent对象。
Tips:
在这里顺带提一下:还记得我们平时写应用Activity时设置的theme或者feature吗(全屏啥的,NoTitle等)?我们一般是不是通过XML的android:theme属性或者java的requestFeature()方法来设置的呢?譬如:
通过java文件设置:requestWindowFeature(Window.FEATURE_NO_TITLE);通过xml文件设置:android:theme="@android:style/Theme.NoTitleBar"
其实我们平时requestWindowFeature()设置的值就是在这里通过getLocalFeature()获取的;而android:theme属性也是通过这里的getWindowStyle()获取的。
setContentView中的onContentChanged()
再回到setContentView中最后的代码部分,可以看见调用了Callback 的onContentChanged函数
final Callback cb = getCallback(); if (cb != null && !isDestroyed()) { cb.onContentChanged(); }
看见没有,首先通过getCallback获取对象cb(回调接口),PhoneWindow没有重写Window的这个方法,所以到抽象类Window中可以看到:
public final Callback getCallback() { return mCallback; }
这个mCallback在哪赋值的呢,继续看Window类发现有一个方法,如下:
blic void setCallback(Callback callback) { mCallback = callback; }
Window中的mCallback是通过这个方法赋值的,那就回想一下,Window又是Activity的组合成员,那就是Activity一定调运这个方法了,回到Activity发现在Activity的attach方法中进行了设置,如下
final void attach(Context context, ActivityThread aThread, ...... mWindow.setCallback(this); ...... }
也就是说Activity类实现了Window的Callback接口。那就是看下Activity实现的onContentChanged方法。如下:
public void onContentChanged() { }
咦?onContentChanged是个空方法。那就说明当Activity的布局改动时,即setContentView()或者addContentView()方法执行完毕时就会调用该方法。所以当我们写App时,Activity的各种View的findViewById()方法等都可以放到该方法中,系统会帮忙回调。
- android setContentView()
- android setContentView
- android setContentView
- Android setContentView的位置
- Android setContentView、LayoutInflater、findViewById
- Android中的setContentView用法
- Android OnCreate、setContentView方法
- Android setContentView()解读
- Android setContentView源码解析
- Android setContentView源码解析
- Android中的setContentView( )方法
- Android源码解析setContentView
- Android setContentView()源码解析
- android setContentView()原理
- Android setContentView的用法
- Android setcontentview过程
- Android setContentView()源码解析
- Android setContentView() 详解
- foreach 循环,删除list中的元素是报错
- 一些简单的输入框限制输入方法
- 软件是如何驱动硬件的,代码是怎样对计算机实现控制的?
- hdu 4280 Island Transport 【图论-网络流-ISAP+栈优化】
- 第X大的数 (sdut oj)
- android setContentView
- C# MessageBox 消息对话框
- Android数据加密之Des加密
- Xcode常用的快捷键
- EasyUI 扩展自定义EasyUI校验规则 验证规则(常用的)
- Android打包失败Proguard returned with error code 1. See console
- 常用springboot注解
- RelativeLayout布局中linearlayout布局居中
- 图片压缩