大家都知道在Activity的onCreate()中调用Activity.setContent()方法能够载入布局文件以设置该Activity的显示界面。本文将从setContentView()的源代码谈起。分析布局文件载入所涉及到的调用链。

本文所用的源代码为android-19.

Step 1  、Activity.setContentView(intresId)

public void setContentView(int layoutResID) {
getWindow().setContentView(layoutResID);
initActionBar();
} public Window getWindow() {
return mWindow;
}

该方法调用了该Activity成员的mWindow,mWindow为Window对象。Windown对象是一个抽象类,提供了标准UI的显示策略和行为策略。在SDK中仅仅有PhoneWindow类实现了Window类。而Window中的setContentView()为空函数,所以最后调用的是PhoneWindow对象的方法。

Step 2  、PhoneWindow.setContentView()

@Override
public void setContentView(int layoutResID) {
if (mContentParent == null) {
installDecor();
} else {
mContentParent.removeAllViews();
}
// 将布局文件加入到mContentParent中
mLayoutInflater.inflate(layoutResID, mContentParent);
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
}

该方法首先依据mContentParent是否为空对mContentParent进行对应的设置。mContentParent为ViewGroup类型,若其已经初始化了,则移除全部的子View。否则调用installDecor()初始化。

接着将资源文件转成View树,并加入到mContentParent视图中。

Step 3、 PhoneWindow.installDecor() 

这段代码比較长,以下的伪代码仅仅介绍逻辑,读者可自行查看源代码。

private void installDecor() {
if (mDecor == null) {
/*创建一个DecorView对象并设置对应的属性。 DecorView是全部View的根View*/
mDecor = generateDecor();
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
}
if (mContentParent == null) {
/*创建mContentParent对象*/
mContentParent = generateLayout(mDecor); // Set up decor part of UI to ignore fitsSystemWindows if appropriate.
mDecor.makeOptionalFitsSystemWindows(); mTitleView = (TextView)findViewById(com.android.internal.R.id.title);
if (mTitleView != null) { mTitleView.setLayoutDirection(mDecor.getLayoutDirection());
// 依据features值,设置Title的相关属性
if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
View titleContainer = findViewById(com.android.internal.R.id.title_container);
if (titleContainer != null) {
titleContainer.setVisibility(View.GONE);
} else {
mTitleView.setVisibility(View.GONE);
}
if (mContentParent instanceof FrameLayout) {
((FrameLayout)mContentParent).setForeground(null);
}
} else {
mTitleView.setText(mTitle);
}
} else {
//若没有Title。则设置ActionBar的相关属性。如回调函数、风格属性
mActionBar = (ActionBarView) findViewById(com.android.internal.R.id.action_bar);
if (mActionBar != null) {
//....... // 推迟调用invalidate,放置onCreateOptionsMenu在 onCreate的时候被调用
mDecor.post(new Runnable() {
public void run() {
// Invalidate if the panel menu hasn't been created before this.
PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
if (!isDestroyed() && (st == null || st.menu == null)) {
invalidatePanelMenu(FEATURE_ACTION_BAR);
}
}
});
}
}
}
}

创建mContentParent对象的代码例如以下:

protected ViewGroup generateLayout(DecorView decor) {
// Apply data from current theme.
//获取当前Window主题的属性数据,相关字段的文件位置为:sdk\platforms\android-19\data\res\values\attrs.xml
//这些属性值能够在AndroidManifest.xml中设置Activityandroid:theme="",也能够在Activity的onCreate中通过
//requestWindowFeature()来设置.注意,该方法一定要在setContentView之前被调用
TypedArray a = getWindowStyle();
//获取android:theme=""中设置的theme
//依据主题属性值来设置PhoneWindow的特征与布局。包含Title、ActionBar、ActionBar的模式、Window的尺寸等属性。
//........ // Inflate the window decor.
// 依据上面设置的Window feature来确定布局文件
// Android SDK内置布局目录位置为:sdk\platforms\android-19\data\res\layout
典型的窗体布局文件有:
R.layout.dialog_titile_icons R.layout.screen_title_icons
R.layout.screen_progress R.layout.dialog_custom_title
R.layout.dialog_title
R.layout.screen_title // 最经常使用的Activity窗体修饰布局文件
R.layout.screen_simple //全屏的Activity窗体布局文件 int layoutResource;
int features = getLocalFeatures(); //会调用requesetWindowFeature()
// ......
mDecor.startChanging();
// 将布局文件转换成View数。然后加入到DecorView中
View in = mLayoutInflater.inflate(layoutResource, null);
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
//取出作为Content的ViewGroup。 android:id="@android:id/content",是一个FrameLayout
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
if (contentParent == null) {
throw new RuntimeException("Window couldn't find content container view");
} if ((features & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0) {
ProgressBar progress = getCircularProgressBar(false);
if (progress != null) {
progress.setIndeterminate(true);
}
} // 将顶层Window的背景、标题、Frame等属性设置成曾经的
if (getContainer() == null) {
//......
} mDecor.finishChanging(); return contentParent;
}

总结:setContentView将布局文件载入到程序窗体的过程可概况为:

1、创建一个DecorView对象。该对象将作为整个应用窗体的根视图

2、依据android:theme=""或requestWindowFeature的设定值设置窗体的属性,依据这些属性选择载入系统内置的布局文件

3、从载入后的布局文件里取出id为content的FrameLayout来作为Content的Parent

4、将setContentView中传入的布局文件载入到3中取出的FrameLayout中





最后。当AMS(ActivityManagerService)准备resume一个Activity时,会回调该Activity的handleResumeActivity()方法,

该方法会调用Activity的makeVisible方法 ,显示我们刚才创建的mDecor视图族。

//系统resume一个Activity时,调用此方法
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
ActivityRecord r = performResumeActivity(token, clearHide);
//...
if (r.activity.mVisibleFromClient) {
r.activity.makeVisible();
}
}

makeVisible位于ActivityThread类中,代码例如以下:

void makeVisible() {
if (!mWindowAdded) {
ViewManager wm = getWindowManager(); // 获取WindowManager对象
wm.addView(mDecor, getWindow().getAttributes());
mWindowAdded = true;
}
mDecor.setVisibility(View.VISIBLE); //使其处于显示状况
}

參考文章:http://blog.csdn.net/qinjuning/article/details/7226787

Android布局文件的载入过程分析:Activity.setContentView()源代码分析的更多相关文章

  1. Xamarin Android布局文件没有智能提示

    Xamarin Android布局文件没有智能提示 在Visual Studio 2015中,Android项目的Main.axml文件没有智能提示,不便于布局文件的编写.解决办法:(1)从Xamar ...

  2. Android布局文件夹引起的问题

    Android 运行到setContentView(R.layout.splash); 总是出现如下的错误: java.lang.RuntimeException: Unable to start a ...

  3. NullPointerException空指针异常——没有事先加载布局文件到acitivy——缺少:setContentView(R.layout.activity_setup_over);

    空指针异常: 04-27 01:13:57.270: E/AndroidRuntime(4942): FATAL EXCEPTION: main04-27 01:13:57.270: E/Androi ...

  4. android 布局文件中控件ID、name标签属性的命名包含“@”、“.”、“+”等等符号的含义

    1. 在项目的根目录有个配置文件“AndroidManifest.xml”,是用来设置Activity的属性的如 <?xml version="1.0" encoding=& ...

  5. android 布局文件中xmlns:android="http://schemas.android.com/apk/res/android"

    http://blog.163.com/benben_long/blog/static/199458243201411394624170/ xmlns:android="http://sch ...

  6. Android之View绘制流程开胃菜---setContentView(...)详细分析

    版权声明:本文出自汪磊的博客,转载请务必注明出处. 1 为什么要分析setContentView方法 作为安卓开发者相信大部分都有意或者无意看过如下图示:PhoneWindow,DecorView这些 ...

  7. Android布局文件layout.xml的一些属性值

        第一类:属性值 true或者 false android:layout_centerHrizontal 水平居中 android:layout_centerVertical 垂直居中 andr ...

  8. Android布局文件-错误

    View requires API level 14 (current min is 8): <?xml version="1.0" encoding="utf-8 ...

  9. android 布局文件 ScrollView 中的 listView item 显示不全解决方案

    import android.content.Context;import android.util.AttributeSet;import android.widget.ListView; /** ...

随机推荐

  1. Debian9.5系统DHCP服务器ISC DHCP软件配置说明

    DHCP 全称Dynamic Host configuration protocol, 动态主机配置协议.是一个局域网的网络协议,使用UDP协议工作,它可以为客户机自动分配IP地址.子网掩码以及缺省网 ...

  2. Linxu基本指令

    一.Linux权限的概念 Linux下有两种用户:普通用户和超级用户(). 普通用户:在linux下做有限的事情: 超级用户:可以在linux系统下做任何事情,不受限制. 普通用户的提示符是“$”,超 ...

  3. ORACLE查询优化之is null和is not null优化

    最近工作的时候遇到了比较大的数据查询,自己的sql在数据量小的时候没问题,在数据量达到300W的时候特别慢,只有自己优化sql了,以前没有优化过,所以记录下来自己的优化过程,本次是关于is null和 ...

  4. [ZJOI2007]捉迷藏 (点分树+堆*3)

    点分树一点都不会啊(还是太菜了) 点分树就是我们点分治构成的新树.满足深度很小. 然后我们就可以在上面瞎维护东西了. 三个大根堆: \(C[u]\)里装的是点分树中u的子树所有点到点分树中u的父亲的距 ...

  5. BZOJ 2938 [POI2000]病毒 (剪枝/A*迭代搜索)

    LOJ BZOJ 题目大意:给你一些模式串,问是否存在一个无限长的文本串,不包含任何一个给定的模式串 并没有想到去模拟合法的文本串在模式串的Trie图上匹配的过程..我好菜啊 如果一个字符串合法,那么 ...

  6. syn攻击原理与防护措施

    何为syn攻击? 先普及下tcp3次握手的知识,在TCP/IP中,tcp协议提供可靠的socket连接服务,通过3次握手建立可靠连接. tcp3次握手过程: 第一阶段:某终端向服务器发送syn(syn ...

  7. C语言实现的minixml解析库入门教程

    minixml的中文说明手册:MiniXML中文文档.dochttp://wenku.baidu.com/view/25fd7d7f31b765ce050814f7.html xml源代码: < ...

  8. vim 常用变量

    为了vim更好的支持python写代码,修改tab默认4个空格有两种设置方法: 1. vim /etc/vimrc 1 set ts=4 2 set sw = 4 2. vim /etc/vimrc ...

  9. Java Bean 简单介绍及其应用

    Bean的中文含义是"豆子",顾名思义JavaBean是一段Java小程序.JavaBean实际上是指一种特殊的Java类.它通经常使用来实现一些比較经常使用的简单功能.并能够非常 ...

  10. Thinking in States

    Thinking in States Niclas Nilsson PEOPLE IN THE REAL WORLD HAVE A WEIRD RELATIONSHIP WITH STATE. Thi ...