Android setContentView方法解析(一)
在Activity的生命周期onCreate中。我们一般都习惯性的调用setContentView(int layoutResID)方法,把布局文件载入到页面上来。以下我们就来通过源代码一步步的分析怎么载入的。
在Activity中,调用的是Window的setContentView
public void setContentView(int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
我们通过源代码发现Window是一个抽象类。并且 getWindow()返回的仅仅是一个mWindow。
public Window getWindow() {
return mWindow;
}
那么mWindow是在什么地方初始化的。我们继续查看源代码,终于发现是在一个叫attach的方法中调用,但是终于我们没有发现调用attach的方法,事实上这种方法是在ActivityThread这个类中调用的。这个类非常重要,包含在main方法中初始化Looper,在这里先不说,以后在介绍。
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
…………
Activity activity = null;
activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
…………
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
…………
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config);
…………
return activity;
}
接着我们在attach方法中看到这样一行代码
mWindow = PolicyManager.makeNewWindow(this);
继续查看,找到PolicyManager这个类,
private static final String POLICY_IMPL_CLASS_NAME =
"com.android.internal.policy.impl.Policy";
…………
Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME);
sPolicy = (IPolicy)policyClass.newInstance();
…………
public static Window makeNewWindow(Context context) {
return sPolicy.makeNewWindow(context);
}
继续,在Policy这个类中我们找到
public Window makeNewWindow(Context context) {
return new PhoneWindow(context);
}
也就是说最初我们找到mWindow就是PhoneWindow,我们继续。不要闲着,
public class PhoneWindow extends Window implements MenuBuilder.Callback
我们通过源代码发现PhoneWindow事实上就是Window。先回到我们刚才说的
getWindow().setContentView(layoutResID);这种方法,事实上就是调用PhoneWindow的setContentView(layoutResID);方法。我们通过源代码继续查看
@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();
}
}
我们先简单分析一下下半部分。假设Callback不为空且没有被销毁的情况下会调用onContentChanged()方法。通过源代码我们发现事实上Activity是实现了Callback接口的
public class Activity extends ContextThemeWrapper
implements LayoutInflater.Factory2,
Window.Callback, KeyEvent.Callback,
OnCreateContextMenuListener, ComponentCallbacks2,
Window.OnWindowDismissedCallback
并且在onContentChanged()方法中是空实现,什么都没做。
public void onContentChanged() {
}
我们再来分析上半部分,假设mContentParent 不为空的话,首先移除全部的子View,removeAllViews方法是ViewGroup类中,View中没有。我们能够先大致看一下。以后在做具体介绍
/**
* Call this method to remove all child views from the
* ViewGroup.
*
* <p><strong>Note:</strong> do not invoke this method from
* {@link #draw(android.graphics.Canvas)}, {@link #onDraw(android.graphics.Canvas)},
* {@link #dispatchDraw(android.graphics.Canvas)} or any related method.</p>
*/
public void removeAllViews() {
removeAllViewsInLayout();
requestLayout();
invalidate(true);
}
假设mContentParent 为空的话,调用 installDecor();进行初始化,接着我们看一下 installDecor();方法的详细实现。
private void installDecor() {
if (mDecor == null) {
mDecor = generateDecor();
…………
}
if (mContentParent == null) {
mContentParent = generateLayout(mDecor);
mTitleView = (TextView)findViewById(com.android.internal.R.id.title);
…………
mActionBar = (ActionBarView) findViewById(com.android.internal.R.id.action_bar);
…………
}
}
首先推断mDecor是否为空,假设为空就调用 generateDecor();我们接着看它详细怎么实现
protected DecorView generateDecor() {
return new DecorView(getContext(), -1);
}
我们发现就一行代码,那么DecorView又是什么,我们继续查看,
private final class DecorView extends FrameLayout implements RootViewSurfaceTaker
最终找到了,原来继承的是FrameLayout ,看到这里可能有的人会恍然大悟,由于我们知道在Activity的setContentView中载入的根布局事实上就是FrameLayout 。这里的FrameLayout 有两部分组成,一部分是系统自定义的title。一部分是content,就是我们自定义的布局,还有,在之前假设我们不须要title的话,我们会在AcdroidMainfest中 android:theme="@android:style/Theme.NoTitleBar",或者在activity中设置requestWindowFeature(Window.FEATURE_NO_TITLE);可是要设置在setContentView之前,好了,上面的代码我们先分析到这,以后有时间还会接着继续写。欢迎拍砖。
Android setContentView方法解析(一)的更多相关文章
- 【Android 多媒体开发】 MediaPlayer 状态机 接口 方法 解析
作者 : 韩曙亮 转载请著名出处 : http://blog.csdn.net/shulianghan/article/details/38487967 一. MediaPlayer 状态机 介绍 ...
- Android Service完全解析,关于服务你所需知道的一切(下)
转载请注册出处:http://blog.csdn.net/guolin_blog/article/details/9797169 在上一篇文章中,我们学习了Android Service相关的许多重要 ...
- Android Service完全解析,关于服务你所需知道的一切(上)
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/11952435 相信大多数朋友对Service这个名词都不会陌生,没错,一个老练的A ...
- Android IntentService完全解析 当Service遇到Handler
一 概述 大家都清楚,在Android的开发中,凡是遇到耗时的操作尽可能的会交给Service去做,比如我们上传多张图,上传的过程用户可能将应用置于后台,然后干别的去了,我们的Activity就很可能 ...
- android源码解析(十七)-->Activity布局加载流程
版权声明:本文为博主原创文章,未经博主允许不得转载. 好吧,终于要开始讲讲Activity的布局加载流程了,大家都知道在Android体系中Activity扮演了一个界面展示的角色,这也是它与andr ...
- Android实现XML解析技术
转载:Android实现XML解析技术 本文介绍在Android平台中实现对XML的三种解析方式. XML在各种开发中都广泛应用,Android也不例外.作为承载数据的一个重要角色,如何读写XML成为 ...
- 36、Android Bitmap 全面解析
Android Bitmap 全面解析(一)加载大尺寸图片 http://www.eoeandroid.com/thread-331669-1-1.html Android Bitmap 全面解析(二 ...
- 【转】Android Service完全解析,关于服务你所需知道的一切(下) ---- 不错
原文网址:http://blog.csdn.net/guolin_blog/article/details/9797169 转载请注册出处:http://blog.csdn.net/guolin_bl ...
- Android ActionBar完全解析,使用官方推荐的最佳导航栏(上)
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/18234477 本篇文章主要内容来自于Android Doc,我翻译之后又做了些加工 ...
随机推荐
- Python 字典和json的本质区别(个人理解)
个人理解:字典和json显示的时候差不多,但是数据类型不同(如下图): 字典的类型是字典dict json的类型是字符串str 接口测试是传参数payload时有时候是传的字符串,应该将payload ...
- 深入分析Android动画(二)
上回书说到Android动画的分类以及基本使用,这会书主要说Android属性动画的原理,对于View动画的原理本篇不做深入分析.对于Android动画的基础请看深入分析Android动画(一) 我们 ...
- 呵呵哒,LNMP下通过fread方式下载文件时,中文名称文件找不到文件
哎,整整折腾一个下午. 本来好好的,thinkphp 自动的uniq方式保存的文件名,非要使用原文件名,真心蛋疼~~ 然后就只好写个脚本 把原来的所有文件都重新命名一下 - - 然后把数据库对应字段也 ...
- CLR类型设计之参数传递
写到这篇文章的时候,笔者回忆起来以前的开发过程中,并没有注意参数的传递是以值传递还是引用传递的,也是第一次了解到可变参数params,常用的不一定就代表理解,可能只是会用.接下来我们就一起回忆一下关于 ...
- 【Java入门提高篇】Day2 接口
上一篇讲完了抽象类,这一篇主要讲解比抽象类更加抽象的内容--接口. 什么是接口呢?先来看个栗子: /** * @author Frank * @create 2017/11/22 * @descrip ...
- Postman+newman+jenkins构建
最近忙着项目接口测试,经过不同工具的对比,发现postman使用起来挺顺手的,所以马上决定使用这个工具进行接口测试工作.刚开始的时候,了解了下接口测试的相关信息,直接着手编写接口测试的测试用例信息 ...
- 熟悉的“if __name__ == '__main__':”究竟是啥?
print(__name__) # 直接手动运行,打印"__main__",当做模块导入(别处import)时打印脚本名字即"name_main" if __n ...
- 教你3分钟读懂HTML5语言的特点
HTML5的跨平台技术 HTML5技术跨平台,适配多终端.传统移动终端上的Native App,开发者的研发工作必须针对不同的操作系统进行,成本相对较高.Native App对于用户还存在着管理成本. ...
- 作为函数的mixin
作为函数的mixin 在一个 mixin 内部定义的变量或 mixin,都调用者可见,因此,它们可以作为它的返回值.如,以下Less代码: .count(@x, @y) { @sum:(@x ...
- 并发容器之写时拷贝的 List 和 Set
对于一个对象来说,我们为了保证它的并发性,通常会选择使用声明式加锁方式交由我们的 Java 虚拟机来完成自动的加锁和释放锁的操作,例如我们的 synchronized.也会选择使用显式锁机制来主动的控 ...