美文网首页
Android Activity,View ,Window三者之

Android Activity,View ,Window三者之

作者: keepWriteCode | 来源:发表于2019-06-04 10:18 被阅读0次
Activity,View ,Window三者之间的关系简述

1.Activity是Android四大组件之一,是负责与用户交互的界面,是视图的载体。
2.Window也是一个抽象的概念,PhoneWindow才是Window的具体唯一实现。
3.View是Android视图的抽象,是Android所有视图组件的父类。DecorView是Activity里的根视图,相当于ViewRoot

4.三者的关系简而言之就是Activity持有一个PhoneWindow实例,PhoneWindow持有一个DecorView的实例。View负责绘制视图组件,Window负责管理View,而Activity负责展示视图和交互。
5.在Activity的onCreate方法里面初始化布局调用setContent时,初始化布局的工作并不是Activity完成的,实际上调用的是PhoneWindow的setContent方法,也就是说布局的初始化工作是Window完成的。而PhoneWindow初始化时会new一个DecorView,通过DecorView可以对View进行管理。
下面我们来看源码的调用顺序
Activity的setContent方法

public void setContentView(@LayoutRes int layoutResID) {
        // 第一步初始化PhoneWindow并调用PhoneWindow的setContentView
        getWindow().setContentView(layoutResID);
        // 第二步初始化Window里的DecorView
        initWindowDecorActionBar();
    }

getWindow方法

public Window getWindow() {
        return mWindow;
    }

mWindow就是PhoneWindow的实例,是在Activity的attach函数里初始化的

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, String referrer, IVoiceInteractor voiceInteractor,
            Window window, ActivityConfigCallback activityConfigCallback) {
        attachBaseContext(context);

        mFragments.attachHost(null /*parent*/);
      // 初始化Window的唯一实现PhoneWindow
        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        ...
    }

initWindowDecorActionBar方法

private void initWindowDecorActionBar() {
        Window window = getWindow();

        // Initializing the window decor can change window feature flags.
        // Make sure that we have the correct set before performing the test below.
        // 初始化DecorView
        window.getDecorView();
        ...

PhoneWindow里的getDecorView方法

@Override
    public final View getDecorView() {
        if (mDecor == null || mForceDecorInstall) {
            installDecor();
        }
        return mDecor;
    }

PhoneWindow里的installDecor方法

private void installDecor() {
        mForceDecorInstall = false;
        if (mDecor == null) {
          // 初始化DecorView
            mDecor = generateDecor(-1);
            mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
            mDecor.setIsRootNamespace(true);
            if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
                mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
            }
        } else {
            mDecor.setWindow(this);
        }
        ...
    }

PhoneWindow里真正初始化DecorView的函数generateDecor

protected DecorView generateDecor(int featureId) {
        // System process doesn't have application context and in that case we need to directly use
        // the context we have. Otherwise we want the application context, so we don't cling to the
        // activity.
        Context context;
        if (mUseDecorContext) {
            Context applicationContext = getContext().getApplicationContext();
            if (applicationContext == null) {
                context = getContext();
            } else {
                context = new DecorContext(applicationContext, getContext());
                if (mTheme != -1) {
                    context.setTheme(mTheme);
                }
            }
        } else {
            context = getContext();
        }
        return new DecorView(context, featureId, this, getAttributes());
    }

6.DecorView是顶级View,即View树的根View。且是PhoneWindow持有的DecorView实例,因此在Activity中我们可以通过getWindow().getDecorView()获取到DecorView的实例。

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.i(TAG,getWindow().getDecorView().toString());
    }

打印结果

06-05 06:12:46.649 10415-10415/com.text.demo I/zxq-MainActivity: com.android.internal.policy.PhoneWindow$DecorView{d25bcf1 V.E...... R.....ID 0,0-0,0}

7.总结
Activity在onCreate之前会调用attach方法,在attach方法中会创建PhoneWindow对象,此时还没有创建 DecorView 对象。在Activity中调用setContentView,实际调用PhoneWindow的setContentView,这时会检查DecorView是否存在,如果不存在则创建DecorView,然后把Activity中的View 添加到 DecorView 中。

相关文章

网友评论

      本文标题:Android Activity,View ,Window三者之

      本文链接:https://www.haomeiwen.com/subject/kufcxctx.html