Android View体系(六)从源码解析Activity的构成
前言
本来这篇是要讲View的工作流程的,View的工作流程主要指的measure、layout、draw这三大流程,在讲到这三大流程之前我们有必要要先了解下Activity的构成,所以就有了这篇文章。
1.从源码解析Activity的构成
当我们写Activity时会调用setContentView()方法,来加载布局,来看看setContentView()方法是怎么实现的(Activity.java):
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
这里调用了getWindow().setContentView(layoutResID),getWindow()指的是什么呢?接着往下看,getWindow()返回mWindow
public Window getWindow() {
return mWindow;
}
在Activity的attach()方法发现mWindow:
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor) {
attachBaseContext(context); mFragments.attachHost(null /*parent*/); mWindow = new PhoneWindow(this);
...省略
}
原来mWindow指的就是PhoneWindow,PhoneWindow是继承抽象类Window的,这样就知道getWindow()得到的是一个PhoneWindow,我们来看看PhoneWindow.java的setContentView()方法(PhoneWindow.java)
@Override
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 {
mContentParent.addView(view, params);
}
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
}
在第5行看到了 installDecor()方法,来看看这个方法里写了什么:
if (mDecor == null) {
mDecor = generateDecor();
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != ) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
}
if (mContentParent == null) {
mContentParent = generateLayout(mDecor);
}
...省略
}
...省略
}
再接着追踪看看generateDecor()方法里写了什么:
protected DecorView generateDecor() {
return new DecorView(getContext(), -);
}
这里创建了一个DecorView,这个DecorView就是Activity中的根View。接着查看DecorView的源码,发现DecorView是PhoneWindow类的内部类,并且继承FrameLayout。我们再来看看第10行generateLayout()方法:
protected ViewGroup generateLayout(DecorView decor) {
...省略
//根据不同的情况加载不同的布局给layoutResource
int layoutResource;
int features = getLocalFeatures();
// System.out.println("Features: 0x" + Integer.toHexString(features));
if ((features & (( << FEATURE_LEFT_ICON) | ( << FEATURE_RIGHT_ICON))) != ) {
if (mIsFloating) {
TypedValue res = new TypedValue();
getContext().getTheme().resolveAttribute(
com.android.internal.R.attr.dialogTitleIconsDecorLayout, res, true);
layoutResource = res.resourceId;
} else {
layoutResource = com.android.internal.R.layout.screen_title_icons;
}
// XXX Remove this once action bar supports these features.
removeFeature(FEATURE_ACTION_BAR);
// System.out.println("Title Icons!");
} else if ((features & (( << FEATURE_PROGRESS) | ( << FEATURE_INDETERMINATE_PROGRESS))) !=
&& (features & ( << FEATURE_ACTION_BAR)) == ) {
// Special case for a window with only a progress bar (and title).
// XXX Need to have a no-title version of embedded windows.
layoutResource = com.android.internal.R.layout.screen_progress;
// System.out.println("Progress!");
} else if ((features & ( << FEATURE_CUSTOM_TITLE)) != ) {
// Special case for a window with a custom title.
// If the window is floating, we need a dialog layout
if (mIsFloating) {
TypedValue res = new TypedValue();
getContext().getTheme().resolveAttribute(
com.android.internal.R.attr.dialogCustomTitleDecorLayout, res, true);
layoutResource = res.resourceId;
} else {
layoutResource = com.android.internal.R.layout.screen_custom_title;
}
// XXX Remove this once action bar supports these features.
removeFeature(FEATURE_ACTION_BAR);
...省略 mDecor.startChanging();
//将layoutResource加载到View中并添加到DecorView中
View in = mLayoutInflater.inflate(layoutResource, null);
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
...省略 }
第42行加载layoutResource的布局,来看看其中的一种布局R.layout.screen_title,这个文件在frameworks\base\core\res\res\layout目录中(screen_title.xml)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:fitsSystemWindows="true">
<!-- Popout bar for action modes -->
<ViewStub android:id="@+id/action_mode_bar_stub"
android:inflatedId="@+id/action_mode_bar"
android:layout="@layout/action_mode_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="?attr/actionBarTheme" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="?android:attr/windowTitleSize"
style="?android:attr/windowTitleBackgroundStyle">
<TextView android:id="@android:id/title"
style="?android:attr/windowTitleStyle"
android:background="@null"
android:fadingEdge="horizontal"
android:gravity="center_vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
<FrameLayout android:id="@android:id/content"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight=""
android:foregroundGravity="fill_horizontal|top"
android:foreground="?android:attr/windowContentOverlay" />
</LinearLayout>
上面的ViewStub是用来显示ActionBar的,下面的两个FrameLayout,一个是title用来显示标题,一个是content用来显示内容。
2.图解Activity的构成
看到如上的源码大家就知道了一个Activity包含一个window对象,这个对象是由PhoneWindow来实现的,PhoneWindow将DecorView做为整个应用窗口的根View,而这个DecorView又将屏幕划分为两个区域一个是TitleView一个是ContentView,而我们平常做应用所写的布局正是展示在ContentView中的。
Android View体系(六)从源码解析Activity的构成的更多相关文章
- Android View 事件分发机制 源码解析 (上)
一直想写事件分发机制的文章,不管咋样,也得自己研究下事件分发的源码,写出心得~ 首先我们先写个简单的例子来测试View的事件转发的流程~ 1.案例 为了更好的研究View的事件转发,我们自定以一个My ...
- Android IntentService使用介绍以及源码解析
版权声明:本文出自汪磊的博客,转载请务必注明出处. 一.IntentService概述及使用举例 IntentService内部实现机制用到了HandlerThread,如果对HandlerThrea ...
- 【Android应用开发】EasyDialog 源码解析
示例源码下载 : http://download.csdn.net/detail/han1202012/9115227 EasyDialog 简介 : -- 作用 : 用于在界面进行一些介绍, 说明; ...
- Android Handler机制(四)---Handler源码解析
Handler的主要用途有两个:(1).在将来的某个时刻执行消息或一个runnable,(2)把消息发送到消息队列. 主要依靠post(Runnable).postAtTime(Runnable, l ...
- Android View事件分发-从源码分析
View事件分发-从源码分析 学习自 <Android开发艺术探索> https://blog.csdn.net/qian520ao/article/details/78555397?lo ...
- Android Handler机制(三)----Looper源码解析
一.Looper Looper对象,顾名思义,直译过来就是循环的意思,从MessageQueue中不断取出message. Class used to run a message loop for a ...
- Android Handler机制(二)---MessageQueue源码解析
MessageQueue 1.变量 private final boolean mQuitAllowed;//表示MessageQueue是否允许退出 @SuppressWarnings(" ...
- Android FM 模块学习之四 源码解析(1)
Normal 0 7.8 磅 0 2 false false false EN-US ZH-CN X-NONE MicrosoftInternetExplorer4 前一章我们了解了FM手动调频,接下 ...
- Android FM模块学习之四源码解析(一)
转自:http://blog.csdn.net/tfslovexizi/article/details/41516149?utm_source=tuicool&utm_medium=refer ...
随机推荐
- HDU 5517---Triple(二维树状数组)
题目链接 Problem Description Given the finite multi-set A of n pairs of integers, an another finite mult ...
- resin远程调试配置
1.进入resin的安装路径下的conf目录,下面有个resin.conf的文件,打开它,将下面这段配置添加进去,然后重启resin(大家应该知道如何重启吧): <jvm-arg>-Xde ...
- DataFrame基本操作
这些操作在网上都可以百度得到,为了便于记忆自己再根据理解总结在一起.---------励志做一个优雅的网上搬运工 1.建立dataframe (1)Dict to Dataframe df = pd. ...
- RC1015 cannot open include file 'atlres.h'
fatal error RC1015: cannot open include file 'atlres.h' 问题:此问题是由于rc文件没有找到 atlres.h导致的 (原因不详) 解决:工程 ...
- 新电脑一般javaweb配置
下个jdk (官网)1.打开我的电脑--属性--高级--环境变量 2.新建系统变量JAVA_HOME 和CLASSPATH 变量名:JAVA_HOME 变量值:C:\Program Files\Jav ...
- Adam
Adam 方法 Adam 方法将惯性保持和环境感知这两个优点集于一身.一方面, Adam 记录梯度的一阶矩(first moment),即过往梯度与当前梯度的平均,这体现了惯性保持:另一方面,Adam ...
- [TensorFlow] Introducing TensorFlow Feature Columns
Welcome to Part 2 of a blog series that introduces TensorFlow Datasets and Estimators. We're devotin ...
- 使用flexible适配移动端h5页面
flexible是淘宝提供的一套REM手机适配的库,用法也非常简单 首先,在页面中引入相关资源 包括flexible.js和flexible_css.js(用于清除默认样式),或者通过cdn方式引入 ...
- SpringBoot(3) 文件上传和访问
springboot文件上传 MultipartFile file,源自SpringMVC MultipartFile 对象的transferTo方法,用于文件保存(效率和操作比原先用FileOutS ...
- Struts2学习(四)———— ognl表达式、值栈、actionContext之间的关系
一.什么是Ognl? 通过百度百科查询到的解释,其中详细的说明了OGNL的作用. 下面我们就对OGNL这5个作用进行讲解 1.存取对象的任意属性,简单说就是对javabean进行操作(重要) 2.调用 ...