• Android 中Activity,Window和View之间的关系


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

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

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

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

        @Override

    public void setContentView(View view, ViewGroup.LayoutParams params) {

    if (mContentParent == null) {

    installDecor();

    else {

                mContentParent.removeAllViews();

            }

    mContentParent.addView(view, params);

    final Callback cb = getCallback();

    if (cb != null) {

                cb.onContentChanged();

            }

        }

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

    private void installDecor() {

    if (mDecor == null) {

    mDecor = generateDecor();

    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 (mContentParent instanceof FrameLayout) {

    null);

                        }

    else {

                        mTitleView.setText(mTitle);

                    }

                }

            }

        }

    Activity--->Window--->DecorView

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

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

     

    final void attach(Context context, ActivityThread aThread,

    int ident,

                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对象如下:

    public PhoneWindow makeNewWindow(Context context) {

    return new PhoneWindow(context);

     }

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

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

    generateDecor直接new了一个DecorView对象:  

    protected DecorView generateDecor() {

    return new DecorView(getContext(), -1);

     }

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

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

    mContentParent.addView(view, params);

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

    现在总结一下:

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

  • 相关阅读:
    C#多线程学习笔记(三)——线程池
    html解析工具
    怎么样获取手机的主题
    我改进的《豆瓣搜》前后对比及源代码
    【收藏】Silverlight Style (二) 自定义样式在后台代码中应用
    C#多线程学习笔记(一)
    学习Linux——学习正确的思考方式(转)
    电信禁路由上网的破解方法
    印度软件业
    中国与印度软件工程师之比较
  • 原文地址:https://www.cnblogs.com/wxishang1991/p/4882765.html
Copyright © 2020-2023  润新知