`

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
分享到:
评论
发表评论

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

相关推荐

    Android代码-Immersive

    Immersive.setContentView(this, R.layout.activity_main, R.color.blue, R.color.green, false, false); } } 使用以下方法代替Activity.setContentView(),即可实现沉浸式。 /** * @param activity 当前需要...

    Activity使用setContentView切换界面

    Activity使用setContentView切换界面

    Android开发教程_012_创建Activity调用setContentView 标清.flv

    Android开发教程_012_创建Activity调用setContentView 标清

    谈谈Android里的Context的使用

    import android.app.Activity; import android.content.Context; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.Button; import ...

    Android代码-可以在 Activity, Fragment, ViewGroup 设置“加载中,空,错误,成功,请求”多种状态。

    PageStateLayout PageStateLayout could let you show [Loading][Empty][Error][Succeed][Requesting] state in ...//replace activity.setContentView() pageStateLayout.load(activity, succeedView); //parent

    Android平台的JavaScript引擎DuktapeJava.zip

    activity.setContentView(R.layout.activity_duk) button1 = activity.findViewById(R.id.button1); button1.setOnClickListener(new OnClickListener(function(){ Toast.makeText(activity, "Button1 Clicked",...

    android的Tag标签的实现

    setContentView(R.layout.main); //取得TabHost对象 mTabHost = getTabHost(); /* 为TabHost添加标签 */ //新建一个newTabSpec(newTabSpec) //设置其标签和图标(setIndicator) //设置内容...

    Android之泡泡效果bubble.rar

    import android.app.Activity; import android.content.Context; import android.graphics.drawable.AnimationDrawable; import android.os.Bundle; import android.view.MotionEvent; import android.view.View; ...

    Android:Handler的post()方法和Thread的start()方法执行Thread的run()方法的区别

    setContentView(R.layout.activity_main); System.out.println("Activity--&gt;"+ Thread.currentThread().getId()); System.out.println("Activity--&gt;"+ Thread.currentThread().getName()); } Runnable r...

    浅析Android Dialog中setContentView()方法

    Dialog在Android中是一个很优秀的工具。在使用Dialog时,我们一般都会自定义要显示的内容布局。Dialog自带了三个方法来支持自定义内容布局。 public void setContentView (int layoutResID); public void ...

    Android代码-动态改变状态栏颜色

    StatusBarColorCompat Change the StatusBarColor dynamically, works on Android 4.4 . 简单优雅地动态改变状态栏颜色,...Activity.setContentView(int layoutResID) StatusBarColorCompat will fetch the colorPri

    android百度地图

    setContentView(R.layout.activity_main); mMapView = (MapView) findViewById(R.id.bmapview); } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); ...

    Android开发教程笔记完全版

    import android.app.Activity; import android.os.Bundle; import android.widget.TextView; public class Hello extends Activity { /** Called when the activity is first created. */ @Override ...

    Android代码-TutoShowcase

    A simple and Elegant Showcase view for Android TutoShowcase.from(this) .setContentView(R.layout.tuto_sample) .on(R.id.about) //a view in actionbar .addCircle() .withBorder() .onClick(new ...

    深入Android开发全方位指南.docx

    项目结构: MainActivity.java: java Copy code package ... setContentView(R.layout.activity_main); } } activity_main.xml: xml Copy code &lt;RelativeLayout xmlns:android="http://schemas.andro

    phonegap 配置文件(android+eclipse+phonegap(cordova)配置项目 .)

    5.2去掉import部分的import android.app.Activity;并加上import org.apache.cordova.*; 5.3修改src文件下的java文件,把class extends 的activity改成DroidGap 5.4把 setContentView() line with super.loadUrl...

    新版Android开发教程.rar

    的 Android SDK 提供了在 Android 平台上使用 JaVa 语言进行 Android 应用开发必须的工具和 API 接口。 特性 • 应用程序框架 支持组件的重用与替换 • Dalvik Dalvik Dalvik Dalvik 虚拟机 专为移动设备优化 • ...

    android界面效果全汇总

    android界面效果全汇总 (一)Activity页面切换的效果 Android 2.0之后有了overridePendingTransition() ,其中里面两个参 数,一个是前一个activity的退出两一个activity的进入, Java代码 1. @Override ...

    Android皮肤架包

    Android皮肤架包,此架包很小,但是包含了更换皮肤的功能,全局可用,详情请认真读此说明:使用架包方法(我们在创建Activity的时候会继承Activity,然而使用此架包我们就继承BaseActivity这个类和Activity没有任何...

    Android实验5-事件处理答案.doc

    import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; public class ...

Global site tag (gtag.js) - Google Analytics