前言

本来这篇是要讲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的构成的更多相关文章

  1. Android View 事件分发机制 源码解析 (上)

    一直想写事件分发机制的文章,不管咋样,也得自己研究下事件分发的源码,写出心得~ 首先我们先写个简单的例子来测试View的事件转发的流程~ 1.案例 为了更好的研究View的事件转发,我们自定以一个My ...

  2. Android IntentService使用介绍以及源码解析

    版权声明:本文出自汪磊的博客,转载请务必注明出处. 一.IntentService概述及使用举例 IntentService内部实现机制用到了HandlerThread,如果对HandlerThrea ...

  3. 【Android应用开发】EasyDialog 源码解析

    示例源码下载 : http://download.csdn.net/detail/han1202012/9115227 EasyDialog 简介 : -- 作用 : 用于在界面进行一些介绍, 说明; ...

  4. Android Handler机制(四)---Handler源码解析

    Handler的主要用途有两个:(1).在将来的某个时刻执行消息或一个runnable,(2)把消息发送到消息队列. 主要依靠post(Runnable).postAtTime(Runnable, l ...

  5. Android View事件分发-从源码分析

    View事件分发-从源码分析 学习自 <Android开发艺术探索> https://blog.csdn.net/qian520ao/article/details/78555397?lo ...

  6. Android Handler机制(三)----Looper源码解析

    一.Looper Looper对象,顾名思义,直译过来就是循环的意思,从MessageQueue中不断取出message. Class used to run a message loop for a ...

  7. Android Handler机制(二)---MessageQueue源码解析

    MessageQueue 1.变量 private final boolean mQuitAllowed;//表示MessageQueue是否允许退出 @SuppressWarnings(" ...

  8. Android FM 模块学习之四 源码解析(1)

    Normal 0 7.8 磅 0 2 false false false EN-US ZH-CN X-NONE MicrosoftInternetExplorer4 前一章我们了解了FM手动调频,接下 ...

  9. Android FM模块学习之四源码解析(一)

    转自:http://blog.csdn.net/tfslovexizi/article/details/41516149?utm_source=tuicool&utm_medium=refer ...

随机推荐

  1. 十大经典排序算法+sort排序

    本文转自:十大经典排序算法,其中有动图+代码详解,本文简单介绍+个人理解. 排序算法 经典的算法问题,也是面试过程中经常被问到的问题.排序算法简单分类如下: 这些排序算法的时间复杂度等参数如下: 其中 ...

  2. Linux学习笔记之五————Linux常用命令之用户、权限管理

    一.引言 用户是Unix/Linux系统工作中重要的一环,用户管理包括用户与组账号的管理. 在Unix/Linux系统中,不论是由本机或是远程登录系统,每个系统都必须拥有一个账号,并且对于不同的系统资 ...

  3. Intellij新安装初始化配置

    自动编译开关 忽略大小写开关 IDEA默认是匹配大小写,此开关如果未关.你输入字符一定要符合大小写.比如你敲string是不会出现代码提示或智能补充.但是,如果你开了这个开关,你无论输入String或 ...

  4. Python编码和Unicode

    原文链接: ERIC MORITZ   翻译: 伯乐在线- 贱圣OMG译文链接: http://blog.jobbole.com/50345/ 我确定有很多关于Unicode和Python的说明,但为 ...

  5. struts2 拦截器弊端

    struts2 怎样在action内获得fielderror

  6. 从零开始学 Web 之 Ajax(七)跨域

    大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...

  7. Springboot+Thymeleaf+layui框架的配置与使用

    前言Springboot默认是不支持JSP的,默认使用thymeleaf模板引擎.所以这里介绍一下Springboot使用Thymeleaf的实例以及遇到的问题. 配置与使用1.在applicatio ...

  8. GTest的安装与使用

    安装GTest 1.安装源代码 下载gtest,release-1.8.0 git clone https://github.com/google/googletest gtest编译 cd goog ...

  9. linux centos7 root密码重置

    转:http://blog.chinaunix.net/uid-21209618-id-4738916.html 分类: LINUX 三年左右没接触linux技术工作,忘记的有很多.不知该怎么去运用. ...

  10. React Native顶|底部导航使用小技巧

    导航一直是App开发中比较重要的一个组件,ReactNative提供了两种导航组件供我们使用,分别是:NavigatorIOS和Navigator,但是前者只能用于iOS平台,后者在ReactNati ...