2024年最新Android --- View,安卓面试刷题

结尾

好了,今天的分享就到这里,如果你对在面试中遇到的问题,或者刚毕业及工作几年迷茫不知道该如何准备面试并突破现状提升自己,对于自己的未来还不够了解不知道给如何规划,可以来看看同行们都是如何突破现状,怎么学习的,来吸收他们的面试以及工作经验完善自己的之后的面试计划及职业规划。

这里放上一部分我工作以来以及参与过的大大小小的面试收集总结出来的一套进阶学习的视频及面试专题资料包,主要还是希望大家在如今大环境不好的情况下面试能够顺利一点,希望可以帮助到大家~

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

}

这里我们看到,通过层层调用,最终会调用到 LayoutInflator#inflate(int, ViewGroup, boolean) 方法,很明显,这个方法会将我们传入的布局 id 转换为 XmlResourceParser,然后进行另一次,也是最后一次重载。

这个方法就厉害了,这里基本上包括了我们所有问题的答案,我们继续往下看。

源码分析


话不多说,上代码。接下来我们来逐段分析下这个 inflate 方法:

public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {

final Context inflaterContext = mContext;

final AttributeSet attrs = Xml.asAttributeSet(parser);

// 默认返回结果为传入的根布局

View result = root;

// 通过 createViewFromTag() 方法找到传入的 layoutId 的根布局,并赋值给 temp

final View temp = createViewFromTag(root, name, inflaterContext, attrs);

ViewGroup.LayoutParams params = null;

// 如果传入的父布局不为空

if (root != null) {

// 为这个 root 生成一套合适的 LayoutParams

params = root.generateLayoutParams(attrs);

if (!attachToRoot) {

// 如果没有 attachToRoot,那为根布局设置 layoutparams

temp.setLayoutParams(params);

}

}

// 如果传入的父布局不为空,且想要 attachToRoot

if (root != null && attachToRoot) {

// 那就将传入的布局以及 layoutparams 通过 addView 方法添加到父布局中

root.addView(temp, params);

}

// 如果传入的根布局为空,或者不想 attachToRoot,则返回要加载的 layoutId

if (root == null || !attachToRoot) {

result = temp;

}

return result;

}

代码也分析完了,我再来总结一下:

  • View#inflate 只是个简易的包装方法,实际上还是调用的 LayoutInflater#inflate ;

  • LayoutInflater#inflate 由于可以自己选择 root 和 attachToRoot

的搭配(后面有解释),使用起来更加灵活;

  • 实际上的区别只是在于 root 是否传空,以及 attachToRoot 真假与否;

  • 当 root 传空时,会直接返回要加载的 layoutId,返回的 View 没有父布局且没有 LayoutParams;

  • 当 root 不传空时,又分为 attachToRoot 为真或者为假:

  • attachToRoot = true 会为传入的 layoutId 直接设置参数,并将其添加到 root 中,然后将传入的 root

返回;

  • attachToRoot = false 会为传入的 layoutId 设置参数,但是不会添加到 root ,然后返回 layoutId

对应的 View;

这里需要注意的是,虽然不马上将 View 添加到 parent 中,但是这里最好也传上 parent,而不是粗暴的传入 null;因为子

View 的 LayoutParams 需要由 parent 来确定;否则会在手动 addView 时调用

generateDefaultLayoutParams() 为子 View 生成一个宽高都为包裹内容的

LayoutParams,而这并不一定是我们想要的。

测试 & 检验


单说起来可能有些抽象,下面使用代码来进行具体的测试与检验。

View.inflate(context, layoutId, null)

如之前所说,这实际上调用的是 getLayoutInflater().inflate(layoutId, null) ,结合之前的源码来看:

public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {

View result = root;

final View temp = createViewFromTag(root, name, inflaterContext, attrs);

if (root == null || !attachToRoot) {

result = temp;

}

return result;

}

很明显,传入的 root 为空,则会直接将加载好的 xml 布局返回,而这种情况下返回的这个 View 没有参数,也没有父布局。

protected void onCreate(@Nullable Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.layout_test);

View inflateView = View.inflate(this, R.layout.layout_basic_use_item, null);

Log.e(“Test”, "LayoutParams -> " + inflateView.getLayoutParams());

Log.e(“Test”, "Parent -> " + inflateView.getParent());

}

在这里插入图片描述

如图所示,正如我们想的,root 传 null 时,参数以及父布局返回结果均为 null。

View.inflate(context, layoutId, mParent)

按之前分析过的,此方法实际调用的是 getLayoutInflater().inflate(layoutId, root, true) ,再来看源码:

public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {

final Context inflaterContext = mContext;

final AttributeSet attrs = Xml.asAttributeSet(parser);

View result = root;

final View temp = createViewFromTag(root, name, inflaterContext, attrs);

ViewGroup.LayoutParams params = null;

if (root != null) {

params = root.generateLayoutParams(attrs);

}

if (root != null && attachToRoot) {

root.addView(temp, params);

}

return result;

}

如源码所示,返回的 result 会在最开始就被赋值为入参的 root,root 不为空,同时 attachToRoot 为 true,就会将加载好的布局直接通过 addView 方法添加到 root 布局中,然后将 root 返回。

protected void onCreate(@Nullable Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.layout_test);

LinearLayout mParent = findViewById(R.id.ll_root);

View inflateView = View.inflate(this, R.layout.layout_basic_use_item, mParent);

Log.e(“Test”, "LayoutParams -> " + inflateView.getLayoutParams());

Log.e(“Test”, "Parent -> " + inflateView.getParent());

Log.e(“Test”, "inflateView -> " + inflateView);

}

在这里插入图片描述

如图示,返回的 View 正是我们传入的 mParent,对应的 id 是 ll_root,参数也不再为空。

getLayoutInflater().inflate(layoutId, root, false)

也许会有人问了,现在要么是 root 传空,返回 layoutId 对应的布局;要么是 root 不传空,返回传入的 root 布局。那我要是想 root 不传空,但是还是返回 layoutId 对应的布局呢?

这就是 View#inflate 的局限了,由于它是包装方法,因此 attachToRoot 并不能因需定制。这时候我们完全可以自己调用 getLayoutInflater().inflate(layoutId, root, false) 方法,手动的将第三个参数传为 false,同时为这个方法传入目标根布局。这样,我们就可以得到一个有 LayoutParams,但是没有 parentView 的 layoutId 布局了。

protected void onCreate(@Nullable Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.layout_test);

LinearLayout mParent = findViewById(R.id.ll_root);

View inflateView = getLayoutInflater().inflate(R.layout.main, mParent, false);

Log.e(“Test”, "LayoutParams -> " + inflateView.getLayoutParams());

Log.e(“Test”, "Parent -> " + inflateView.getParent());

}

在这里插入图片描述

与我们分析的一致,有参数,但是没有父布局,且返回的就是我们加载的布局 id。我们在之后可以通过 addView 方法手动将这个布局加入父布局中。

最后

跳槽季整理面试题已经成了我多年的习惯!在这里我和身边一些朋友特意整理了一份快速进阶为Android高级工程师的系统且全面的学习资料。涵盖了Android初级——Android高级架构师进阶必备的一些学习技能。

附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

[外链图片转存中…(img-eHEhmu4Y-1715906762645)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值