android进阶篇14、UI布局层次结构及布局加载流程源码解析

文章详细分析了AndroidAppCompatActivity中的setContentView方法调用过程,重点讲解了createViewFromTag方法的工作原理,包括Factory接口和视图加载策略。还涉及到了LayoutInflater用于XML解析和View的创建过程。
摘要由CSDN通过智能技术生成

// Decide whether to return the root that was passed in or the
// top view found in xml.
if (root == null || !attachToRoot) {
result = temp; //6
}
return result;
}

3、通过createViewFromTag创建根view,此方法调用链如下所示;注释1处是第一次创建view;注释2和注释3最终都会调用到注释3处的方法;注释1是一种情况,注释3是另一种情况,我们分别讨论一下;

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) {

View view = tryCreateView(parent, name, context, attrs); //1

if (view == null) {
final Object lastContext = mConstructorArgs[0];
mConstructorArgs[0] = context;
try {
if (-1 == name.indexOf(‘.’)) {
view = onCreateView(context, parent, name, attrs); //2
} else {
view = createView(context, name, null, attrs); //3
}
}
}
return view;
}

3-1 tryCreateView

第一种情况tryCreateView方法如下所示,如果mFactory2不为空,会通过注释1处mFactory2的onCreateView方法创建view;如果mFactory不为空,会通过注释2处mFactory的onCreateView创建view;那么这两个factory是什么呢?如注释3和注释4所示,Factory是一个单方法的接口,Factory2继承自Factory,重载了一个onCreateView方法;这两个变量初始都为空,因此我们开发者可以实现这两个接口,然后赋值给这两个变量,这样就会优先通过我们设置的方法加载view了;

public final View tryCreateView(@Nullable View parent, @NonNull String name,
@NonNull Context context,
@NonNull AttributeSet attrs) {
View view;
if (mFactory2 != null) {
view = mFactory2.onCreateView(parent, name, context, attrs); //1
} else if (mFactory != null) {
view = mFactory.onCreateView(name, context, attrs); //2
} else {
view = null;
}
return view;
}

private Factory mFactory; //3
private Factory2 mFactory2; //4
public interface Factory {
View onCreateView(@NonNull String name, @NonNull Context context,
@NonNull AttributeSet attrs);
}
public interface Factory2 extends Factory {
View onCreateView(@Nullable View parent, @NonNull String name,
@NonNull Context context, @NonNull AttributeSet attrs);
}

3-2 createView

因为系统并没有给mFactory和mFactory2赋值,因此会走到createView方法;方法代码如下所示,注释1处首先从sConstructorMap获取构造方法,第一次肯定为空;然后走到注释2处,通过反射获得构造方法,mConstructorSignature这个参数代表的是两个参数的构造方法,因此返回的就是带两个参数的构造方法;接着在注释3处将构造方法放入sConstructorMap中;最后在注释4处通过newInstance方法获取view实例并返回;

public final View createView(@NonNull Context viewContext, @NonNull String name,
@Nullable String prefix, @Nullable AttributeSet attrs)
throws ClassNotFoundException, InflateException {
Constructor<? extends View> constructor = sConstructorMap.get(name); //1

if (constructor == null) {
constructor = clazz.getConstructor(mConstructorSignature); //2
constructor.setAccessible(true);
sConstructorMap.put(name, constructor); //3
}

Object lastContext = mConstructorArgs[0];
mConstructorArgs[0] = viewContext;
Object[] args = mConstructorArgs;
args[1] = attrs;

final View view = constructor.newInstance(args); //4
return view;
}

三、AndroidX的AppCompatActivity源码变化

1、当我们的Activity继承自AppCompatActivity时,setContentView方法会调用到AppCompatActivity的setContentView;因此最终调用的是AppCompatDelegateImpl的setContentView;

AppCompatActivity – setContentView

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

AppCompatActivity – getDelegate

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

AppCompatDelegate – create

public static AppCompatDelegate create(@NonNull Activity activity,
@Nullable AppCompatCallback callback) {
return new AppCompatDelegateImpl(activity, callback);
}
2、AppCompatDelegateImpl的setContentView方法如下所示,注释1处的ensureSubDecor()最终还是会调用到installDecor方法;注释2处用于获得contentParent;注释3处用于将我们的布局添加到contentParent中;
public void setContentView(int resId) {
ensureSubDecor(); //1
ViewGroup contentParent = mSubDecor.findViewById(android.R.id.content); //2
contentParent.removeAllViews();
LayoutInflater.from(mContext).inflate(resId, contentParent);//3
mAppCompatWindowCallback.getWrapped().onContentChanged();
}
这里我就分享一份资料,希望可以帮助到大家提升进阶。

内容包含:Android学习PDF+架构视频+面试文档+源码笔记高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 这几块的内容。分享给大家,非常适合近期有面试和想在技术道路上继续精进的朋友。

如果你有需要的话,可以点击Android学习PDF+架构视频+面试文档+源码笔记获取免费领取方式

喜欢本文的话,不妨给我点个小赞、评论区留言或者转发支持一下呗~

img

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
[外链图片转存中…(img-aCCNsr5W-1710963922245)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值