Window的创建过程

1.activity的window创建

activity的window创建过程跟activity的启动过程息息相关,activity启动过程中最终会由ActivityThread中的performLaunchActivity()方法来完成整个启动,在该方法内部会通过类加载器加载创建activity的实例对象,并且通过attach方法为activity关联运行过程中所依赖的一些列上下文环境。

 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
      ...
             java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);


    ...
            if (activity != null) {
                Context appContext = createBaseContextForActivity(r, activity);
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);
                if (r.overrideConfig != null) {
                    config.updateFrom(r.overrideConfig);

                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window);


        return activity;
    }

在activity的attach方法中系统会创建activity所属的window对象,并为其设置回调接口,如下

        //6.0以上源码
        mWindow = new PhoneWindow(this, window);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
//5.0源码
        mWindow = PolicyManager.makeNewWindow(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);

可以看到不同版本的SDK源码在window创建这里是有点不一样,5.0以下的代码通PolicyManager.makeNewWindow方法来创建window对象,PolicyManager是一个策略类,它的真正实现是Policy类,该类中的makeNewWindow方法实现如下:

public Window  makeNewWindow(Context context){
   return new PhoneWindow(context);
}

从5.0版本源码可以看出最终也是new了一个PhoneWindow对象,而6.0的源码直接mWindow = new PhoneWindow(this, window);,其实两者本质是一样的,。到这里,window已经创建完了,下面分析activity的视图是如何显示在window上的。而 Activity 的视图是由 setContentView 提供,所以从 setContentView 入手,它的源码如下:

public void setContentView(int layoutResID){
   getWindow().setContentView(layoutResID);
   initWindowDecorActionBar();
}

从该方法可以看出,activity将具体的实现交给了window处理,而window的实现类是phonewindow,因此看phonewindow中的setContentView方法即可;

 public void setContentView(View view, ViewGroup.LayoutParams params) {
        // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
        // decor, when theme attributes and the like are crystalized. Do not check the feature
        // before this happens.
        //1.如果没有DecorView  就创建它
        if (mContentParent == null) {
            installDecor();
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            mContentParent.removeAllViews();
        }

        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            view.setLayoutParams(params);
            final Scene newScene = new Scene(mContentParent, view);
            transitionTo(newScene);
        } else {
        //将2.view添加到DecorView的mContentParent
        //6.0的写法
            mContentParent.addView(view, params);
        //5.0的写法:
            //mLayoutInflater.inflate(layoutResID, mContentParent);
        }
        mContentParent.requestApplyInsets();
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }
        mContentParentExplicitlySet = true;
    }

该方法有下面几个步骤:

1.如果没有DecorView 就创建它

DecorView 是activity中的顶级view,它的创建过程由installDecor方法来完成,该方法内部会通过generateDecor方法来直接创建DecorView ,这个时候DecorView 还是一个空白的FrameLayout, 接着,为了初始化DecorView 的结构,在installDecor方法内部还会调用generateLayout方法来加载具体的布局文件到DecorView 。

2.将view添加到DecorView的mContentParent

猜你喜欢

转载自blog.csdn.net/xj531/article/details/81781785