Android GUI之Activity、Window、View
相信大家在接触Android之初就已经知道了Activity中的setContentView方法的作用了,很明显此方法是用于为Activity填充相应的布局的。那么,Activity是如何将填充的布局绘制出来的呢?实际上Activity将View的绘制与显示交给了Window对象来处理,下面我们通过源码来进行跟踪分析。
Activity的源码如下,只给出我们关注的部分:
- public class Activity extends ContextThemeWrapper
- implements LayoutInflater.Factory2,
- Window.Callback, KeyEvent.Callback,
- OnCreateContextMenuListener, ComponentCallbacks2,
- Window.OnWindowDismissedCallback {
- ……
- ……
- private Window mWindow;
- private WindowManager mWindowManager;
- ……
- /**
- * Retrieve the current {@link android.view.Window} for the activity.
- * This can be used to directly access parts of the Window API that
- * are not available through Activity/Screen.
- *
- * @return Window The current window, or null if the activity is not
- * visual.
- */
- public Window getWindow() {
- return mWindow;
- }
- ……
- /**
- * Set the activity content from a layout resource. The resource will be
- * inflated, adding all top-level views to the activity.
- *
- * @param layoutResID Resource ID to be inflated.
- *
- * @see #setContentView(android.view.View)
- * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
- */
- public void setContentView(int layoutResID) {
- getWindow().setContentView(layoutResID);
- initWindowDecorActionBar();
- }
- /**
- * Set the activity content to an explicit view. This view is placed
- * directly into the activity's view hierarchy. It can itself be a complex
- * view hierarchy. When calling this method, the layout parameters of the
- * specified view are ignored. Both the width and the height of the view are
- * set by default to {@link ViewGroup.LayoutParams#MATCH_PARENT}. To use
- * your own layout parameters, invoke
- * {@link #setContentView(android.view.View,android.view.ViewGroup.LayoutParams)}
- * instead.
- *
- * @param view The desired content to display.
- *
- * @see #setContentView(int)
- * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
- */
- public void setContentView(View view) {
- getWindow().setContentView(view);
- initWindowDecorActionBar();
- }
- 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, IVoiceInteractor voiceInteractor) {
- attachBaseContext(context);
- mFragments.attachActivity(this, mContainer, null);
- mWindow = PolicyManager.makeNewWindow(this);
- ……
- }
- ……
- }
PolicyManager的部分源码:
- public final class PolicyManager {
- ……
- private static final IPolicy sPolicy;
- static {
- // Pull in the actual implementation of the policy at run-time
- ……
- sPolicy = (IPolicy)policyClass.newInstance();
- ……
- }
- // Cannot instantiate this class
- private PolicyManager() {}
- // The static methods to spawn new policy-specific objects
- public static Window makeNewWindow(Context context) {
- return sPolicy.makeNewWindow(context);
- }
- ……
- }
Policy的部分源码:
- public class Policy implements IPolicy {
- ……
- public Window makeNewWindow(Context context) {
- return new PhoneWindow(context);
- }
- ……
- }
从给出的源码我们可以看到,Activity内部含有一个Window类型的对象mWindow,当我们调用setContentView方法时,实际上是委托给了Window对象进行处理。Window本身是一个抽象类,它描述了android窗口的基本属性和行为特征。在activity的attach方法中通过mWindow = PolicyManager.makeNewWindow(this)创建了Window对象。通过追踪代码可知, PolicyManager.makeNewWindow(this)实际上是调用Policy中的makeNewWindow方法,在此方法中创建了一个PhoneWindow对象。而PhoneWindow正是Window的子类。他们的关系图如下:
继续追踪源码,PhoneWindow对Window的抽象方法setContentView(int layoutResId)进行了实现,具体源码如下:
- @Override
- 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) {
- installDecor();
- } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
- mContentParent.removeAllViews();
- }
- if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
- final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
- getContext());
- transitionTo(newScene);
- } else {
- mLayoutInflater.inflate(layoutResID, mContentParent);
- }
- final Callback cb = getCallback();
- if (cb != null && !isDestroyed()) {
- cb.onContentChanged();
- }
- }
在这个方法中我们可以看到首先对mContentParent进行了判断,如果为空的话则调用installDecor方法,通过hasFeature判断window是否具备某些特征,如果窗口不含有FEATURE_CONTENT_TRANSITIONS特征,则清空mContentParent中的所有子元素,为后面加载布局文件到mContentParent中做好准备。通过后面的判断,我们也可以看出无论走那个分支,其实都是对mContentParent布局内容做了更新。由此我们可以推断出mContentParent其实就是我们自己的布局的存放容器,它在PhoneWindow中定义如下:
- // This is the view in which the window contents are placed. It is either
- // mDecor itself, or a child of mDecor where the contents go.
- private ViewGroup mContentParent;
那么mContentParent是在哪里被创建的呢,很显然是在方法installDecor中,方法installDecor的关键代码如下:
- private void installDecor() {
- if (mDecor == null) {
- mDecor = generateDecor();
- ……
- }
- if (mContentParent == null) {
- mContentParent = generateLayout(mDecor);
- ……
- }
- }
在这个方法中,我们可以看到,首先对mDecor进行判断,如果为空在调用generateDecor方法生成mDecor对象,那么mDecor对象是什么呢?通过查看代码,可以知道mDecor的类型为DecorView,此类型是定义在PhoneWindow中的一个内部类,它继承了FrameLayout。紧接着判断mContentParent是否为空,为空则调用generateLayout并通过传入参数mDecor生成了mContentParent对象。在这个方法中通过应用的主题、窗口特征等来确定使用的布局资源并将使用的布局添加mDecor中,而这些布局中都会含有一个id为content的ViewGroup(FrameLayout),此ViewGroup正是mContentParent,方法关键代码如下:
- protected ViewGroup generateLayout(DecorView decor) {
- ……
- View in = mLayoutInflater.inflate(layoutResource, null);
- decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
- mContentRoot = (ViewGroup) in;
- ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
- ……
- return contentParent;
- }
由此我们可以确定,view的显示处理顺序为Activity->PhoneWindow->DecorView->ViewGroup(mContentView)->自定义的View(布局)。
Activity中显示视图的层次结构,具体如下:
疑问咨询或技术交流,请加入官方QQ群: (452379712)
出处:http://www.cnblogs.com/jerehedu/
本文版权归烟台杰瑞教育科技有限公司和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
Android GUI之Activity、Window、View的更多相关文章
- Activity Window View的关系
http://blog.csdn.net/chiuan/article/details/7062215 http://blog.163.com/fenglang_2006/blog/static/13 ...
- activity window view 关系
1.Activity , Window和View的关系是什么? 跟踪Activity的源码就会发现:Activity.attch() -> PolicyManager -> Policy ...
- Activity Window View WindowManager关系&Touch事件分发机制
http://www.cnblogs.com/linjzong/p/4191891.html https://www.cnblogs.com/kest/p/5141817.html https://b ...
- android中activity,window,view之间的关系
activity:控制单元 window:承载模型 view:显示视图 几个小tip: 1.一个 Activity 构造的时候一定会构造一个 Window(PhoneWindow),并且只有一个 2. ...
- android 中的 window,view,activity具体关系
通过讨论这个问题,我们能够见识到google是对面向对象模式的理解,能够理解android底层的一些调用.这也是一道很常见的面试题. 我们这篇文章就来解决这四个问题: Android 中view的显 ...
- 图解Android - Android GUI 系统 (2) - 窗口管理 (View, Canvas, Window Manager)
Android 的窗口管理系统 (View, Canvas, WindowManager) 在图解Android - Zygote 和 System Server 启动分析一 文里,我们已经知道And ...
- android应用开发之Window,View和WindowManager .
ViewManager vm = a.getWindowManager(); vm.add(view,l); window :一个抽象的窗口基类,控制顶层窗口的外观和行为.作为顶层窗口,可控制窗口背 ...
- View, Activity, Window
View, Activity, Window 2010-03-02 10:42:56| 分类: android|举报|字号 订阅 对于屏幕显示而言,整个是window,这个window里显示 ...
- Android GUI之View绘制流程
在上篇文章中,我们通过跟踪源码,我们了解了Activity.Window.DecorView以及View之间的关系(查看文章:http://www.cnblogs.com/jerehedu/p/460 ...
随机推荐
- python 全栈开发,Day137(爬虫系列之第4章-scrapy框架)
一.scrapy框架简介 1. 介绍 Scrapy一个开源和协作的框架,其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的,使用它可以以快速.简单.可扩展的方式从网站中提取所需的数据.但目前S ...
- python 全栈开发,Day102(支付宝支付)
昨日内容回顾 1. django请求生命周期? - 当用户在浏览器中输入url时,浏览器会生成请求头和请求体发给服务端 请求头和请求体中会包含浏览器的动作(action),这个动作通常为get或者po ...
- python 全栈开发,Day54(jQuery的属性操作,使用jQuery操作input的value值,jQuery的文档操作)
昨日内容回顾 jQuery 宗旨:write less do more 就是js的库,它是javascript的基础上封装的一个框架 在前端中,一个js文件就是一个模块 一.用法: 1.引入包 2.入 ...
- node.js认识及学习资料
2011年阿里就已经开始在生产环境中使用nodejs. 阿里的技术栈中,Java是最核心的,Nodejs扮演怎样的一个角色? 1. 基础设施大部分采用Java实现,变化较少,有事务要求的Busines ...
- 结构型模式之Adapter模式
适配器模式把一个类的接口变换成客户端所期待的另一种接口. 在JDK中的体现 把一个接口或类变成另外一种. java.util.Arrays#asList()javax.swing.JTable(Tab ...
- #8 //HDU 5730 Shell Necklace(CDQ分治+FFT)
Description 给出长度分别为1~n的珠子,长度为i的珠子有a[i]种,每种珠子有无限个,问用这些珠子串成长度为n的链有多少种方案 题解: dp[i]表示组合成包含i个贝壳的项链的总方案数 转 ...
- 安装oracle11g时遇到INS-13001环境不满足最低要求
在安装oracle11g,点击setup.exe之后,弹出了如下提示框: 解决方法: 首先,打开你解压后的database文件夹,找到stage,然后cvu,找到cvu_prereq.xml文件,用记 ...
- 085 HBase的二级索引,以及phoenix的安装(需再做一次)
一:问题由来 1.举例 有A列与B列,分别是年龄与姓名. 如果想通过年龄查询姓名. 正常的检索是通过rowkey进行检索. 根据年龄查询rowkey,然后根据rowkey进行查找姓名. 这样的效率不高 ...
- Flutter常用组件(Widget)解析-Text
单一格式的文本. 文本组件是以字符串形式显示的单一格式,这个文本字符串可以是多行显示也可以是单独一行显示,主要取决于你的布局限制. 这样式内容是可选择的,如果你省略了,则会使用文本的默认样式来显示.如 ...
- [洛谷P2066]机器分配
题目描述 总公司拥有高效设备M台,准备分给下属的N个分公司.各分公司若获得这些设备,可以为国家提供一定的盈利.问:如何分配这M台设备才能使国家得到的盈利最大?求出最大盈利值.其中M≤15,N≤10.分 ...