转自:http://hi.baidu.com/xiaofanqing/blog/item/8261ac114ab14f64cb80c435.html

我想大多数人,对于这3个东西的概念能区分,但是具体区别在哪却很难说出来。

我这里根据我个人的理解来讲讲我个人对这3个概念的理解。当然这里设计到通用的事件窗口模型等通用GUI设计,我这里就不打算讲了,纯粹从概念上来进行区分。

Activity是Android应用程序的载体,允许用户在其上创建一个用户界面,并提供用户处理事件的API,如onKeyEvent, onTouchEvent等。 并维护应用程序的生命周期(由于android应用程序的运行环境和其他操作系统不同,android的应用程序是运行在框架之内,所以他的应用程序不能当当从进程的级别去考虑,而更多是从概念上去考虑。android应用程序是由多个活动堆积而成,而各个活动又有其独立的生命周期)。Activity本身是个庞大的载体,可以理解成是应用程序的载体,如果木有Activity,android应用将无法运行。也可以理解成android应用程序的入口。Acivity的实例对象由系统维护。系统服务ActivityManager负责维护Activity的实例对象,并根据运行状态维护其状态信息。

但在用户级别,程序员可能根愿意理解成为一个界面的载体。但仅仅是个载体,它本身并不负责任何绘制。Activity的内部实现,实际上是聚了一个Window对象。Window是一个抽象类,它的具体是在android_src_home/framework/policies/base/phone/com/android/internal/policy/impl目录下的PhoneWindow.java。

当我们调用Acitivity的 setContentView方法的时候实际上是调用的Window对象的setContentView方法,所以我们可以看出Activity中关于界面的绘制实际上全是交给Window对象来做的。绘制类图的话,可以看出Activity聚合了一个Window对象。

下面是PhoneWindow中的setContentView方法的实现:

@Override

publicvoidsetContentView(View view, ViewGroup.LayoutParams params) {

if(mContentParent ==null) {

installDecor();

}else{

mContentParent.removeAllViews();

}

mContentParent.addView(view, params);

finalCallback cb = getCallback();

if(cb !=null) {

cb.onContentChanged();

}

}

Window内部首先判断mContentParent是否为空,然后调用installDecor方法(安装装饰器),我们看看这个方法如何实现的

privatevoidinstallDecor() {

if(mDecor ==null) {

mDecor = generateDecor();

mDecor.setIsRootNamespace(true);

}

if(mContentParent ==null) {

mContentParent = generateLayout(mDecor);

mTitleView = (TextView)findViewById(com.android.internal.R.id.title);

if(mTitleView !=null) {

if((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {

View titleContainer = findViewById(com.android.internal.R.id.title_container);

if(titleContainer !=null) {

titleContainer.setVisibility(View.GONE);

}else{

mTitleView.setVisibility(View.GONE);

}

if(mContentParentinstanceofFrameLayout) {

((FrameLayout)mContentParent).setForeground(null);

}

}else{

mTitleView.setText(mTitle);

}

}

}

}

在该方法中,首先创建一个DecorView,DecorView是一个扩张FrameLayout的类,是所有窗口的根View。我们在Activity中调用的setConctentView就是放到DecorView中了。这是我们类图的聚合关系如下:

Activity--->Window--->DecorView

这是我们得出这3个类之间最直接的一个关系。

我们详细分析一下,类对象是如何被创建的。

先不考虑Activity的创建(因为 Acitivity的实例由ActivityManager维护,是在另一个进程设计到IPC的通信,后面会讲到),而考虑Window和View的创建。

Activity被创建后,系统会调用它的attach方法来将Activity添加到ActivityThread当中。我们找到Activity的attach方法如下:

finalvoidattach(Context context, ActivityThread aThread,

Instrumentation instr, IBinder token,intident,

Application application, Intent intent, ActivityInfo info,

CharSequence title, Activity parent, String id,

Object lastNonConfigurationInstance,

HashMap<String,Object> lastNonConfigurationChildInstances,

Configuration config) {

attachBaseContext(context);

mWindow= PolicyManager.makeNewWindow(this);

mWindow.setCallback(this);

if(info.softInputMode!= WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {

mWindow.setSoftInputMode(info.softInputMode);

}

mUiThread= Thread.currentThread();

mMainThread= aThread;

mInstrumentation= instr;

mToken= token;

mIdent= ident;

mApplication= application;

mIntent= intent;

mComponent= intent.getComponent();

mActivityInfo= info;

mTitle= title;

mParent= parent;

mEmbeddedID= id;

mLastNonConfigurationInstance= lastNonConfigurationInstance;

mLastNonConfigurationChildInstances= lastNonConfigurationChildInstances;

mWindow.setWindowManager(null,mToken,mComponent.flattenToString());

if(mParent!=null) {

mWindow.setContainer(mParent.getWindow());

}

mWindowManager=mWindow.getWindowManager();

mCurrentConfig= config;

}

我们看红色的代码部分,就是创建Window对象的代码。感兴趣的同学可以跟踪去看看具体是如何创建的。其实很简单,其内部实现调用了Policy对象的makeNewWindow方法,其方法直接new了一个PhoneWindow对象如下:

publicPhoneWindow makeNewWindow(Context context) {

returnnewPhoneWindow(context);

}

这时我们已经可以把流程串起来,Activity创建后系统会调用其attach方法,将其添加到ActivityThread当中,在attach方法中创建了一个window对象。

下面分析View的创建。我们知道Window聚合了DocerView,当用户调用setContentView的时候会把一颗View树仍给DocerView.View树是已经创建好的实例对象了,所以我们研究的是DocerView是个什么东西,它是如何被创建的。

我们回头看看Window实现里边的setContentView方法,我们看上面代码的红色部分setContentView->installDecor->generateDecor.

generateDecor直接new了一个DecorView对象:

protectedDecorView generateDecor() {

returnnewDecorView(getContext(), -1);

}

我们可以去看看DecorView的实现,它是PhoneWindow的一个内部类。实现很简单,它默认会包含一个灰色的标题栏,然后在标题栏下边会包含一个空白区域用来当用户调用setContentView的时候放置用户View,并传递事件,这里不做详细分析,感兴趣同学可以自己研究研究。

当DecorView创建好之后再回到Window中的setContentView方法中来,见上面代码蓝色部分,调用

mContentParent.addView(view, params);

来将用户的View树添加到DecorView中。

到这时为止,我想我们已经很清晰的认识到它们3者之间的关系,并知道其创建流程。

现在总结一下:

Activity在onCreate之前调用attach方法,在attach方法中会创建window对象。window对象创建时并木有创建Decor对象对象。用户在Activity中调用setContentView,然后调用window的setContentView,这时会检查DecorView是否存在,如果不存在则创建DecorView对象,然后把用户自己的View 添加到DecorView中。


更多相关文章

  1. Crazy Android(安卓)Note
  2. Android(安卓)binder from Top to Bottom
  3. Android改变字体方法——Typeface
  4. 在 Android(安卓)中使用 Java8 的特性!
  5. Android应用程序整合第三方API(以高德Map API为例)
  6. java/android 设计模式学习笔记(1)---单例模式
  7. Android(安卓)取得应用程序的启动次数和运行时间等信息
  8. iOS Tableview侧滑删除和移动cell的实现
  9. 【 Android(安卓)】RecyclerView 使用方法总结

随机推荐

  1. PHP常用字符串函数库
  2. mysql语句、类的自动加载与引用
  3. oracle数据库无法打开修复过程
  4. ADAMoracle去中心化预言机网络如何激励喂
  5. 接口文档生成工具 一键生成文档 ApiPost
  6. PHP学习—数组Array
  7. MySQL DDL命令大全(数据定义语言)
  8. 【前端 · 面试 】TCP 总结(一)—— 概述
  9. 数据库连接及事件委托
  10. 创建用户表