图形系统——1. 布局加载

基于android10开始分析android图形系统
图形系统——1. 布局加载
在这里插入图片描述

1. setContentView

public class MainActivity extends AppCompatActivity {

    public static final String TAG = "_MainActivity_";
    private TextView mTv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //我们研究的就是这个setContentView
        setContentView(R.layout.activity_main);
        mTv = findViewById(R.id.tv);
     
    }
}




2 AppCompatActivity.java

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

@NonNull
public AppCompatDelegate getDelegate() {
    if (mDelegate == null) {
        mDelegate = AppCompatDelegate.create(this, this);
    }
    return mDelegate;
}

3 AppCompatDelegate.java

@NonNull
public static AppCompatDelegate create(@NonNull Activity activity,
                                       @Nullable AppCompatCallback callback) {
    return new AppCompatDelegateImpl(activity, callback);
}

public abstract void setContentView(@LayoutRes int resId);

4 AppCompatDelegateImpl.java

@Override
public void setContentView(int resId) {
    //确保decorView和ContentView存在,如果不存在就创建它  --->第一阶段
    ensureSubDecor();
    //可以看出来android.R.id.content就是我们的contentView的id
    ViewGroup contentParent = mSubDecor.findViewById(android.R.id.content);
    contentParent.removeAllViews();
    //contentView根布局清除完之后才可以填充视图   ---->第二阶段
    LayoutInflater.from(mContext).inflate(resId, contentParent);
    mAppCompatWindowCallback.getWrapped().onContentChanged();
}

4.1 第一阶段

private void ensureSubDecor() {
    if (!mSubDecorInstalled) {
        //检查你的Appcompat属性是否存在,按照你的主题属性来配置Activity
        mSubDecor = createSubDecor();
        ......
    }
}

private ViewGroup createSubDecor() {
    TypedArray a = mContext.obtainStyledAttributes(R.styleable.AppCompatTheme);

    //下面这句太熟悉了,每次我们主题设置设置错误或者没有设置主题就会报错
    if (!a.hasValue(R.styleable.AppCompatTheme_windowActionBar)) {
        a.recycle();
        throw new IllegalStateException(
            "You need to use a Theme.AppCompat theme (or descendant) with this activity.");
    }

    //下面就是根据你的主题属性来配置Activity
    if (a.getBoolean(R.styleable.AppCompatTheme_windowNoTitle, false)) {
        requestWindowFeature(Window.FEATURE_NO_TITLE);
    } else if (a.getBoolean(R.styleable.AppCompatTheme_windowActionBar, false)) {
        // Don't allow an action bar if there is no title.
        requestWindowFeature(FEATURE_SUPPORT_ACTION_BAR);
    }
    if (a.getBoolean(R.styleable.AppCompatTheme_windowActionBarOverlay, false)) {
        requestWindowFeature(FEATURE_SUPPORT_ACTION_BAR_OVERLAY);
    }
    if (a.getBoolean(R.styleable.AppCompatTheme_windowActionModeOverlay, false)) {
        requestWindowFeature(FEATURE_ACTION_MODE_OVERLAY);
    }
    mIsFloating = a.getBoolean(R.styleable.AppCompatTheme_android_windowIsFloating, false);
    a.recycle();

    //下面这两行很重要,涉及到和Window的绑定了
    //所以我们要首先知道这个mWindow到底是什么?
    ensureWindow();


    mWindow.getDecorView(); //代码见 4.3PhoneWindow.java
    ...
    mWindow.setContentView(subDecor);//代码见 4.3PhoneWindow.java
    .....
}

private void ensureWindow() {
    ...
        if (mWindow == null && mHost instanceof Activity) {
            //(Activity) mHost).getWindow()又是什么鬼?
            attachToWindow(((Activity) mHost).getWindow());
        }
    ...
}

private void attachToWindow(@NonNull Window window) {
    ...
    //当前mWindow在此处被唯一赋值,值就是(Activity) mHost).getWindow()
    mWindow = window;
}


//Activity.java

public Window getWindow() {
    return mWindow;
}

//mWindow又在哪里被赋值了呢?
 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, IBinder assistToken) {
     ...
     attachBaseContext(context);
     mWindow = new PhoneWindow(this, window, activityConfigCallback);
      //这句话后面会提到
      mWindow.getLayoutInflater().setPrivateFactory(this);
     ...
 }
//这里的attach方法在哪里被调用了呢?其实就是Activity启动过程中发生的, 代码在ActivityThread.java类

4.2 ActivityThread.java

  private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ...
       //注意这里的outerContext是Activity
       appContext.setOuterContext(activity);
                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, r.configCallback,
                        r.assistToken);
  ...
}

4.3 PhoneWindow.java

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

@Override
public void setContentView(int layoutResID) {

    if (mContentParent == null) {
        installDecor();
    } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        mContentParent.removeAllViews();
    }
    ...
}
private void installDecor() {
    mForceDecorInstall = false;
    if (mDecor == null) {
       //生成DecorView
        mDecor = generateDecor(-1);
       ...
    } else {
        mDecor.setWindow(this);
    }
    if (mContentParent == null) {
       //生成mContentParent
        mContentParent = generateLayout(mDecor);
         ...
    }
  {
    
    protected DecorView generateDecor(int featureId) {
        ...
        //说明一个PhoneWindow也是创建一个DecorView
        return new DecorView(context, featureId, this, getAttributes());
    }
    
     protected ViewGroup generateLayout(DecorView decor) {
        ...
        //去找布局中的ID_ANDROID_CONTENT控件
        ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
        ...
        return contentParent;
     }

4.2 第二阶段

@Override
public void setContentView(int resId) {
    //确保decorView和ContentView存在,如果不存在就创建它  --->第一阶段
    ensureSubDecor();
    //可以看出来android.R.id.content就是我们的contentView的id
    ViewGroup contentParent = mSubDecor.findViewById(android.R.id.content);
    contentParent.removeAllViews();
    //其实这里相当于PhoneWindow暴露出一个对象供需要填充view的类使用
    //contentView根布局清除完之后才可以填充视图   ---->第二阶段
    LayoutInflater.from(mContext).inflate(resId, contentParent);
    mAppCompatWindowCallback.getWrapped().onContentChanged();
}

4.3 LayoutInflater.java

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {
    return inflate(resource, root, root != null);
}

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) {
    ....
   //开始解析我们写的XML文件了
    XmlResourceParser parser = res.getLayout(resource);
    try {
        return inflate(parser, root, attachToRoot);
    } finally {
        parser.close();
    }
    ....
}
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
    ...
     //先去找root节点
     final View temp = createViewFromTag(root, name, inflaterContext, attrs);

    // 解析子view
    rInflateChildren(parser, temp, attrs, true);

    //将所有的节点添加到view树上
   if (root != null && attachToRoot) {
                 root.addView(temp, params);
     }             
}

private View createViewFromTag(View parent, String name, Context context, AttributeSet attrs) {
    return createViewFromTag(parent, name, context, attrs, false);
}


View createViewFromTag(View parent, String name, Context context, AttributeSet attrs,
                       boolean ignoreThemeAttr) {
    ...
    //父类是  AppcompatActivity根据view名称new一个对象出来。
    View view = tryCreateView(parent, name, context, attrs);
    //父类是  Activity 或者是自定义的的View  则反射生成一个view
    if (view == null) {
        final Object lastContext = mConstructorArgs[0];
        mConstructorArgs[0] = context;
        try {
            if (-1 == name.indexOf('.')) {
                view = onCreateView(context, parent, name, attrs);
            } else {
                view = createView(context, name, null, attrs);
            }
        } finally {
            mConstructorArgs[0] = lastContext;
        }
    }
    ...
}

public final View tryCreateView(@Nullable View parent, @NonNull String name,
    @NonNull Context context,
    @NonNull AttributeSet attrs) {
    if (name.equals(TAG_1995)) {
        // Let's party like it's 1995!
        return new BlinkLayout(context, attrs);
    }

  //一脸懵逼mFactory2是什么?mFactor是什么?mPrivateFactor又是什么?
  //首先是mFactory2尝试加载view,如果mFactory2为空才会使用mFactory加载
  //如果两者都为空或者两者创建的view都是空,就会尝试让mPrivateFactory创建一下
    View view;
    if (mFactory2 != null) {
        view = mFactory2.onCreateView(parent, name, context, attrs);
    } else if (mFactory != null) {
        view = mFactory.onCreateView(name, context, attrs);
    } else {
        view = null;
    }

    if (view == null && mPrivateFactory != null) {
        // 4.1 Activity.java   mWindow.getLayoutInflater().setPrivateFactory(this);
        // mPrivateFactory其实就是Activity,所以在这里就是调用Activity的onCreateView
        view = mPrivateFactory.onCreateView(parent, name, context, attrs);
    }
    return view;
}

4.4 Activity.java —> mPrivateFactory

@Nullable
public View onCreateView(@Nullable View parent, @NonNull String name,
        @NonNull Context context, @NonNull AttributeSet attrs) {
    if (!"fragment".equals(name)) {
        //这个name就是view的名字,我们平时声明的都是TextView/Button等等
        return onCreateView(name, context, attrs);
    }
    //所以知道为啥我们要使用<fragment>而不是<Fragment>创建fragment节点了吧
    //只有fragment才会被检测到,通过碎片控制器生成碎片
    return mFragments.onCreateView(parent, name, context, attrs);
}

@Nullable
    public View onCreateView(@NonNull String name, @NonNull Context context,
            @NonNull AttributeSet attrs) {
        //Activity只负责fragment的创建,其他view一律不管
        return null;
    }
//这里就把mPrivateFactory讲完了,我们看下另外两个mFactory和mFactory2

4.5 LayoutInflater.java

//先找到这几个变量定义的地方
@UnsupportedAppUsage
private Factory mFactory;
@UnsupportedAppUsage
private Factory2 mFactory2;

//查询了赋值的操作,共有三处
protected LayoutInflater(LayoutInflater original, Context newContext) {
    ...  
        mFactory = original.mFactory;
    mFactory2 = original.mFactory2;
    mPrivateFactory = original.mPrivateFactory;
    ...
}

public void setFactory(Factory factory) {
    ...
        mFactorySet = true;
    if (mFactory == null) {
        mFactory = factory;
    } else {
        mFactory = new FactoryMerger(factory, null, mFactory, mFactory2);
    }
}

//层层寻找调用此方法的地方,接下来逻辑是倒过来的 调用链从顺序变为倒序
public void setFactory2(Factory2 factory) {
    ...
        mFactorySet = true;
    if (mFactory == null) {
        mFactory = mFactory2 = factory;
    } else {
        mFactory = mFactory2 = new FactoryMerger(factory, factory, mFactory, mFactory2);
    }
}

4.6 LayoutInflaterCompat.java

public static void setFactory2(
    @NonNull LayoutInflater inflater, @NonNull LayoutInflater.Factory2 factory) {
    inflater.setFactory2(factory);

    if (Build.VERSION.SDK_INT < 21) {
        final LayoutInflater.Factory f = inflater.getFactory();
        if (f instanceof LayoutInflater.Factory2) {
            // The merged factory is now set to getFactory(), but not getFactory2() (pre-v21).
            // We will now try and force set the merged factory to mFactory2
            forceSetFactory2(inflater, (LayoutInflater.Factory2) f);
        } else {
            // Else, we will force set the original wrapped Factory2
            forceSetFactory2(inflater, factory);
        }
    }
}

4.7 AppCompatDelegateImpl.java

@Override
public void installViewFactory() {
    LayoutInflater layoutInflater = LayoutInflater.from(mContext);
    if (layoutInflater.getFactory() == null) {
        //传了参数this,说明mFactory2就是AppCompatDelegateImpl实例
        LayoutInflaterCompat.setFactory2(layoutInflater, this);
    } else {
        if (!(layoutInflater.getFactory2() instanceof AppCompatDelegateImpl)) {
            Log.i(TAG, "The Activity's LayoutInflater already has a Factory installed"
                    + " so we can not install AppCompat's");
        }
    }
}

4.8 AppCompatActivity.java

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    final AppCompatDelegate delegate = getDelegate();
    //在这里进行installViewFactory
    delegate.installViewFactory();
    delegate.onCreate(savedInstanceState);
    super.onCreate(savedInstanceState);
}

4.9 MainActivity.java

@Override
protected void onCreate(Bundle savedInstanceState) {
    //父类去执行了注册mFatory2的工作
    super.onCreate(savedInstanceState);
}

现在我们确定了一点,mFactory2在MainActivity.java中的super.onCreate(savedInstanceState)就获得了初始化。mFactory2就是AppCompatDelegateImpl实例化对象,下面回到4.4 LayoutInflater.java代码中继续分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值