`

android Activity.setContentView和Window PhoneWindow类学习

 
阅读更多
文中提到的窗口可泛指我们能看到的界面,包括一个Activity呈现的界面(我们可以将之理解为应用程序窗口),一个Dialog,一个Toast,一个Menu菜单等。
  首先对相关类的作用进行一下简单介绍:

Window 类   位于 /frameworks/base/core/java/android/view/Window.java
   说明:该类是一个抽象类,提供了绘制窗口的一组通用API。可以将之理解为一个载体,各种View在这个载体上显示。
源文件(部分)如下:
public abstract class Window {	
	//...
	//指定Activity窗口的风格类型
    public static final int FEATURE_NO_TITLE = 1;
    public static final int FEATURE_INDETERMINATE_PROGRESS = 5;
    
    //设置布局文件
    public abstract void setContentView(int layoutResID);

    public abstract void setContentView(View view);

    //请求指定Activity窗口的风格类型
    public boolean requestFeature(int featureId) {
        final int flag = 1<<featureId;
        mFeatures |= flag;
        mLocalFeatures |= mContainer != null ? (flag&~mContainer.mFeatures) : flag;
        return (mFeatures&flag) != 0;
    }    
    //...
}


PhoneWindow类  位于/frameworks/policies/base/phone/com/android/internal/policy/impl/PhoneWindow.java
说明: 该类继承于Window类,是Window类的具体实现,即我们可以通过该类具体去绘制窗口。并且,该类内部包含了一个DecorView对象,该DectorView对象是所有应用窗口(Activity界面)的根View。 简而言之,PhoneWindow类是把一个FrameLayout类即DecorView对象进行一定的包装,将它作为应用窗口的根View,并提供一组通用的窗口操作接口。
源文件(部分)如下:      
public class PhoneWindow extends Window implements MenuBuilder.Callback {
	//...
	// This is the top-level view of the window, containing the window decor.
    private DecorView mDecor;  //该对象是所有应用窗口的根视图 , 是FrameLayout的子类
    
    // 该对象是Activity布局文件的父视图,一般来说是一个FrameLayout型的ViewGroup 
    // 同时也是DecorView对象的一个子视图
    // 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; 
    
    //设置标题
    @Override
    public void setTitle(CharSequence title) {
        if (mTitleView != null) {
            mTitleView.setText(title);
        }
        mTitle = title;
    }
    //设置背景图片
    @Override
    public final void setBackgroundDrawable(Drawable drawable) {
        if (drawable != mBackgroundDrawable || mBackgroundResource != 0) {
            mBackgroundResource = 0;
            mBackgroundDrawable = drawable;
            if (mDecor != null) {
                mDecor.setWindowBackground(drawable);
            }
        }
    }
    //...    
}


DecorView类    该类是PhoneWindow类的内部类
说明: 该类是一个FrameLayout的子类,并且是PhoneWindow的子类,该类就是对普通的FrameLayout进行功能的扩展,更确切点可以说是修饰(Decor的英文全称是Decoration,即“修饰”的意思),比如说添加TitleBar(标题栏),以及
TitleBar上的滚动条等 。最重要的一点是,它是所有应用窗口的根View 。
如下所示 :





源文件(部分)如下:
private final class DecorView extends FrameLayout {  
    //...  
    //触摸事件处理  
    @Override  
    public boolean onTouchEvent(MotionEvent event) {  
        return onInterceptTouchEvent(event);  
    }  
    //...  
}  


打个不恰当比喻吧,Window类相当于一幅画(抽象概念,什么画我们未知) ,PhoneWindow为一副齐白石先生的山水画(具体概念,我们知道了是谁的、什么性质的画),DecorView则为该山水画的具体内容(有山、有水、有树,各种界面)。
DecorView呈现在PhoneWindow上。当系统(一般是ActivityManagerService)配置好启动一个Activity的相关参数(包括Activity对象和Window对象信息)后,就会回调Activity的onCreate()方法,在其中我们通过设置setContentView()方法类设置该Activity的显示界面,整个调用链由此铺垫开来。setContentView()的三个构造方法调用流程本质上是一样的,我们就分析setContentView(intresId)方法。

Step 1、Activity.setContentView(intresId)
该方法在Activity类中
该方法只是简单的回调Window对象,具体为PhoneWindow对象的setContentView()方法实现
	public void setContentView(int layoutResID) {
	    getWindow().setContentView(layoutResID);
	}

	public Window getWindow() {
	    return mWindow;   //Window对象,本质上是一个PhoneWindow对象
	}


Step 2 、PhoneWindow.setContentView()
该方法在PhoneWindow类中
	@Override
	public void setContentView(int layoutResID) {
		//是否是第一次调用setContentView方法, 如果是第一次调用,则mDecor和mContentParent对象都为空
	    if (mContentParent == null) {
	        installDecor();
	    } else {
	        mContentParent.removeAllViews();
	    }
	    mLayoutInflater.inflate(layoutResID, mContentParent);
	    final Callback cb = getCallback();
	    if (cb != null) {
	        cb.onContentChanged();
	    }
	}


该方法根据首先判断是否已经由setContentView()了获取mContentParent即View对象, 即是否是第一次调用该PhoneWindow对象setContentView()方法如果是第一次调用,则调用installDecor()方法,否则,移除该mContentParent内
所有的所有子View。
最后将我们的资源文件通过LayoutInflater对象转换为View树,并且添加至mContentParent视图中。

PS:因此,在应用程序里,我们可以多次调用setContentView()来显示我们的界面。

Step 3、 PhoneWindow. installDecor()
该方法在PhoneWindow类中
	private void installDecor() {
	    if (mDecor == null) {
	    	//mDecor为空,则创建一个Decor对象
	        mDecor = generateDecor();
	        mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
	        mDecor.setIsRootNamespace(true);
	    }
	    if (mContentParent == null) {
	    	//generateLayout()方法会根据窗口的风格修饰,选择对应的修饰布局文件
	    	//并且将id为content(android:id="@+id/content")的FrameLayout赋值给mContentParent
	        mContentParent = generateLayout(mDecor);
	        
	        //...
	}


首先、该方法首先判断mDecor对象是否为空,如果不为空,则调用generateDecor()创建一个DecorView(该类是FrameLayout子类,即一个ViewGroup视图) ;

generateDecor()方法原型为:
    protected DecorView generateDecor() {
        return new DecorView(getContext(), -1);
    }


整个过程主要是如何把Activity的布局文件添加至窗口里,上面的过程可以概括为:
1、创建一个DecorView对象,该对象将作为整个应用窗口的根视图
2、创建不同的窗口修饰布局文件,并且获取Activity的布局文件该存放的地方,由该窗口修饰布局文件内id为content的FrameLayout指定 。
3、将Activity的布局文件添加至id为content的FrameLayout内。
最后,当AMS(ActivityManagerService)准备resume一个Activity时,会回调该Activity的handleResumeActivity()方法,
该方法会调用Activity的makeVisible方法 ,显示我们刚才创建的mDecor视图族。

转自:http://blog.csdn.net/qinjuning/article/details/7226787

  • 大小: 39 KB
  • 大小: 26.8 KB
分享到:
评论
发表评论

文章已被作者锁定,不允许评论。

相关推荐

    andriod开发之Activity的渲染机制

    默认情况下,它会加载`com.android.internal.R.layout.activity_window_background`,这是一个包含状态栏和导航栏的布局,但开发者可以通过自定义Theme或直接修改Window属性来改变这一行为。 当布局被加载后,`...

    android启动以及activity生命周期分析

    `PhoneWindow`是Android系统中为Activity提供的一个窗口实现。它是Activity的默认窗口,提供了诸如状态栏、标题栏等功能。 - **PhoneWindow**: 创建PhoneWindow的过程实际上就是在Activity内部创建一个`PhoneWindow...

    第三章:Android控件架构和自定义控件详解.md

    1. 每个Activity都有一个`Window`对象,这个对象通常是由`PhoneWindow`实现的。 2. `PhoneWindow`会将一个`DecorView`作为整个窗口的根View。`DecorView`不仅是一个容器,还封装了一些通用的控件,如状态栏、标题栏...

    深入解析Android中的setContentView加载布局原理

    在Android应用开发中,`setContentView`是一个至关重要的方法,用于将XML布局文件加载到活动(Activity)中,成为用户界面的基础。这个方法是每个Activity生命周期的起点,它告诉系统如何构建活动的视图结构。下面...

    Activity启动流程图

    - PhoneWindow是Activity使用的Window的实现类,它负责承载应用的用户界面。setContentView方法是其一个重要的方法,用于设置Activity的布局。 9. DecorView和contentParent - DecorView是Activity窗口的顶级视图...

    Activity 工作过程1

    在Android系统中,Activity的工作过程是一个复杂且有序的流程,涉及到多个组件和方法的调用。下面我们将深入解析Activity从启动到显示的具体步骤,以及其中的关键知识点。 首先,当一个Activity被启动时,Android...

    Android应用程序窗口(Activity)窗口对象(Window)创建指南

    通过以上步骤,我们可以清晰地看到Activity、Window(PhoneWindow)和Context之间的关系。Activity作为用户交互的入口,通过Window对象来实现具体的UI展示,而Context则提供了运行上下文,使得Activity能够访问系统...

    【Android进阶】(7)系统窗口的调用

    这个默认窗口是由`PhoneWindow`类实现的,它是`Window`类的一个子类,处理着窗口的各种显示逻辑。 系统窗口的创建和管理主要涉及WindowManager服务。WindowManager是Android系统的公共服务接口,允许应用动态地添加...

    windowDecorView关系图

    在Android应用开发中,`Window`、`Activity`和`DecorView`是三个核心概念,它们之间有着紧密的关系。本文将详细阐述在Android 4.0.1版本中,这三者之间的相互作用以及如何建立联系,同时结合提供的"windowDecorView...

    深入理解Android中的Window和WindowManager

    Window不是一个具体的类,而是由抽象类实现,其中最常见的实现是PhoneWindow。在Android中,无论是Activity、Dialog还是Toast,其界面都挂载在一个或多个Window上。WindowManager则是与Window交互的接口,它允许...

    requestWindowFeature

    `Window` 类的实现包括了`PhoneWindow` 和`DecorView` 等组件,它们共同协作构建出Android应用的视觉层次。`PhoneWindow` 是`Activity` 默认使用的`Window` 类,它负责处理`requestWindowFeature` 请求,并将这些...

    Android中activity从创建到显示的基本介绍

    在`attach`过程中,Activity的Window被初始化为PhoneWindow,这是Android系统提供的一个具体实现,它与Activity紧密关联,处理窗口相关的任务。 2. **Activity#onCreate**: `ActivityThread`通过调用`...

    UI底层源码深度剖析手册1

    `setContentView`实际是由`PhoneWindow`实现的,`PhoneWindow`是`Window`类的一个具体实现。`Window`是一个抽象类,其注释指出,只有一个实现类`PhoneWindow`。 在`setContentView`中,`getWindow`返回`mWindow`,...

    windowmanager

    2. Activity中的setContentView方法实际上是在PhoneWindow中添加了一个View或者ViewGroup。这里的View或ViewGroup就是用户界面的基础,它们决定了用户看到的内容。 3. 如果需要在Activity之外显示额外的视图,比如...

    APP开发教程 Java Android移动端开发 4、Android UI进阶(2)-自定义控件 共21页.pptx

    在Android中,Activity通常会创建一个 **PhoneWindow**。 - **Window** 可以通过 `setContentView` 设置一个 **rootView**,通常是 **ViewGroup** 类型,如 `FrameLayout` 或 `LinearLayout`,作为显示内容的基础。...

    Android View源码解读 DecorView与ViewRootImpl浅谈

    在Android应用开发中,View是构建用户界面的基本元素,而DecorView和ViewRootImpl则是连接View与Activity的重要组件。在深入理解View的工作流程,如事件分发、测量、布局和绘制之前,我们需要先探讨Activity如何将UI...

    深入解析Android中View创建的全过程

    总的来说,Android中View的创建涉及多个组件和步骤,包括`Activity`、`Window`、`PhoneWindow`、`LayoutInflater`、`LayoutParams`以及测量、布局和绘制过程。理解这个过程有助于开发者更好地控制界面的显示和性能...

    全面的Android view相关知识汇总整理

    - Activity的`onCreate()`方法中通过`setContentView()`加载布局。 - `onResume()`方法调用后,`DecorView`被添加到`Window`,由`ViewRootImpl`管理。 - `measure()`, `layout()`, `draw()`三个步骤依次执行,...

    view面试专题.docx

    ### View面试专题知识点详解 #### 一、View的滑动方式 在Android开发过程中,对...以上内容覆盖了Android开发中关于View的重要知识点,掌握这些内容有助于开发者更好地理解和优化应用程序中的界面交互与渲染流程。

    WindowSourceCode-windows source code

    phoneWindow到底是什么东西,window和他是什么关系? DecorView是干什么用的?和我们的布局有什么关系? getWindow()。requestFeature移除标题栏,为什么要放到setContentView之前才有效? 继承自活动 点进...

Global site tag (gtag.js) - Google Analytics