AppCompatActivity的setContentView的加载流程分析

1. 概述


上篇文章我们分析了Activity的setContentView的源码,如果对Activity的setContentView的源码不是很清楚的,可以先去看下我之前的文章:

Activity的setContentView的加载流程分析

2. 分析AppCompatActivity的setContentView的源码


1>:点击AppCompatActivity源码中搜索 setContentView,代码如下

@Override
    public void setContentView(@LayoutRes int layoutResID) {
        getDelegate().setContentView(layoutResID);
    }

2>:发现setContentView()方法还是抽象方法:

public abstract void setContentView(@LayoutRes int resId);

3>:点击getDelegate(),代码如下:

public static AppCompatDelegate create(Activity activity, AppCompatCallback callback) {
        return create(activity, activity.getWindow(), callback);
    }

4>:点击create()如下:

private static AppCompatDelegate create(Context context, Window window,
            AppCompatCallback callback) {
        final int sdk = Build.VERSION.SDK_INT;
        if (sdk >= 23) {
            return new AppCompatDelegateImplV23(context, window, callback);
        } else if (sdk >= 14) {
            return new AppCompatDelegateImplV14(context, window, callback);
        } else if (sdk >= 11) {
            return new AppCompatDelegateImplV11(context, window, callback);
        } else {
            return new AppCompatDelegateImplV7(context, window, callback);
        }
    }

会发现 AppCompatActivity会做一些兼容,大于23版本的、大于14版本的、大于11版本的,然后点击AppCompatDelegateImplV23,一路点击进去,发现,最终其实是调用的 AppCompatDelegateImplV7,也就是说最终调用的是AppCompatDelegateImplV7 类下边的 setContentView(),

5>:AppCompatDelegateImplV7 类下边的 setContentView()代码如下:

@Override
    public void setContentView(View v) {
        ensureSubDecor();
        ViewGroup contentParent = (ViewGroup) mSubDecor.findViewById(android.R.id.content);
        contentParent.removeAllViews();
        contentParent.addView(v);
        mOriginalWindowCallback.onContentChanged();
    }

3. AppCompatActivity会拦截View的创建,分析原因


接下来我们就让MainActivity分别继承Activity和AppCompatActivity,然后打印下activity_main中的ImageView,观察打印结果到底有有什么不同。

继承Activity,打印结果如下:
Log.e("TAG", "" + mImageIv);    //  ImageView
继承AppCompatActivity,打印结果如下:
Log.e("TAG", "" + mImageIv);    //  AppCompatImageView

1>:AppCompatActivity设置了Factory,就不会执行系统的onCreateView(),而是去执行自己的onCreateView()方法的逻辑,

    @Override
    public void installViewFactory() {
        LayoutInflater layoutInflater = LayoutInflater.from(mContext);
        if (layoutInflater.getFactory() == null) {
            LayoutInflaterCompat.setFactory(layoutInflater, this);
        } else {
        }
    }

2>:而上边一旦设置了setFactory,也就是说mFactory 不会空,那么它就会执行自己的onCreateView()方法,进而执行自己的一系列流程,就会执行mFactory.onCreateView(name, context, attrs)逻辑;

            View view;
            // 前提是看你有没有设置Factory  继承AppCompatActivity他就设置了
            if (mFactory2 != null) {
                view = mFactory2.onCreateView(parent, name, context, attrs);
            } else if (mFactory != null) {
                view = mFactory.onCreateView(name, context, attrs);
            } else {
                view = null;
            }
            // 通过反射创建View

3>:AppCompatActivity它会执行自己中的方法,然后判断各种 View,从而执行自己对应的 AppCompatTextView、AppCompatImageView等等所有的View,从而达到拦截View的创建,截图如下:


图片.png

由以上可知,AppCompatActivity会拦截View的创建,不会执行系统的onCreateView(),而是执行自己的 onCreateView(),进而去替换一些View,比如上边的TextView、ImageView、Button、EditText、Spinner、ImageButton等所有系统的 View控件。

你可能感兴趣的:(AppCompatActivity的setContentView的加载流程分析)