Android-值得深入思考的几个面试问答分享,2024年最新字节面试题java

// callers should clear, so clear shouldn’t be necessary, but for safety…
mPreSortedChildren.clear();
mPreSortedChildren.ensureCapacity(childrenCount);
}

final boolean customOrder = isChildrenDrawingOrderEnabled();
for (int i = 0; i < childrenCount; i++) {
// add next child (in child order) to end of list
final int childIndex = getAndVerifyPreorderedIndex(childrenCount, i, customOrder);
final View nextChild = mChildren[childIndex];
final float currentZ = nextChild.getZ();

// insert ahead of any Views with greater Z
int insertIndex = i;
while (insertIndex > 0 && mPreSortedChildren.get(insertIndex - 1).getZ() > currentZ) {
insertIndex–;
}
mPreSortedChildren.add(insertIndex, nextChild);
}
return mPreSortedChildren;
}

它里面是通过一个getAndVerifyPreorderedIndex方法来获取对应的子VIew索引,这个方法要传进去一个叫customOrder的boolean。

这个customOrder,看名字可以知道,是自定义顺序的意思,如果它为true的话,接着会通过getChildDrawingOrder(int childCount, int i)方法来获取对应的索引,而且,这个方法是protected的,所以我们可以通过重写这个方法并根据参数"i"来决定返回哪一个View所对应的索引,从而改变分发的顺序。

protected int getChildDrawingOrder(int childCount, int i) {
return i;
}

那这个customOrder,什么时候为true呢?

在buildOrderedChildList方法里可以看到这么一句:

final boolean customOrder = isChildrenDrawingOrderEnabled();

emmmm,也就是说,如果要自定义这个顺序的话,还需要调用setChildrenDrawingOrderEnabled(true)来开启。

重新捋一捋流程:

1. setChildrenDrawingOrderEnabled(true)来开启自定义顺序;
2. 重写getChildDrawingOrder方法来决定什么时候要返回哪个子View;

###2. AppCompatTextView 与 TextView 有什么区别?

1. compat库是如何将TextView替换为AppCompatTextVew的?
2. 为什么要进行替换?
3. 根据替换相关原理,我们可以做哪些事情?

####先从第二问开始吧:

AppCompatTextView继承自TextView,是对TextView的一种扩展,因为在5.0中首次推出了MaterialDesign这种设计风格。

但是众所周知的,5.0推出不可能所有的设备全都一下子更新到最新版本,为了在早期版本上实现新的功能(这些新功能比如从源码注释中解读到比如backgroundTint属性,根据文本内容自适应大小等).

即为了新特性同样可以兼容老版本,framework在创建TextView实例的时候,自动帮我们进行了替换。

其它的AppCompatXXX与XXX的关系也是如此。

####第一问:

然后第一问,如何完成替换的,我们这里只拿最直观的流程举例,且尽可能的简化源码过程,在讨论这个问题之前,先了解几个预备知识:

View是怎么被解析创建出来的:

**1.LayoutInflater:**将布局XML文件实例化为其对应的View对象,我们在Activity中通过setContentView传入一个Layout的资源文件id,最终该方法最终会调用到PhoneWindow的setContentView方法,这个方法里面有调用到

mLayoutInflater.inflate(layoutResID, mContentParent);

2.inflate方法,该方法的作用是将指定的XML文件填充到View的层次结构中去,最终无论通过什么途径调用到inflate方法,都会走到三个参数的重载方法这里:

return inflate(parser, root, attachToRoot);

parser你可以认为持有将Layout.XML解析后的数据。后两个参数的意义如下:

1. root为null,attchToRoot无意义,inflate返回的是当前XML对应的根布局。
2. root不为null且attachToRoot为true,则整个XML对应的布局就设置了根布局是root。
3. root不为null且attachToRoot为false,则会将root的layoutParames设置给当前XML的布局。

知道了LayoutInflate.inflate做了什么,再往下,inflate中会调用createViewFromTag,从方法名就能知道,继续往下走,我们离答案越来越近了。

createViewFromTag做的事情非常有意思:

先看到787行这个if-else,条件是name中有没有"."字符,如果有我们会执行onCreateView,如果没有会执行createView。

####name啥时候有点?

自定义控件的时候。

当是系统控件的时候,createView会有一个填充了第二个参数的调用:

createView(name, “android.view.”, attrs);补上了View控件的全路径名,而自定义控件则不需要,因为传入的name就是一个全路径名。

####为什么要全路径名?

因为View控件对象的创建是通过反射来实现的:

clazz = mContext.getClassLoader().loadClass(
prefix != null ? (prefix + name) : name).asSubclass(View.class);

constructor = clazz.getConstructor(mConstructorSignature);
constructor.setAccessible(true);
sConstructorMap.put(name, constructor);
// …
args[1] = attrs;
final View view = constructor.newInstance(args);

下面对这几步做一个总结:

XML中保存了ViewTree的结构和View的相关标签信息(包括View的类型和一些属性值),然后这些信息会在后面通过反射的方式(如果没有Factory2和Factory的话)创建实例对象,如果创建的是ViewGroup,则会对它的子View遍历重复创建步骤,创建完View对象后,会add到对应的ViewGroup中。

其中相关方法的调用流程是:

inflate->rInflate->createViewFromTag->createView。

好像还是没有看到替换?

还是上一张图,我们只解释了后半部分,没有解释前半部分,那么什么是Factory?

继续往下看:

createViewFromTag中会先判断有没有Factory或者Factory2的对象,如果有,则调用Factory的onCreateView方法。

这两个类都是接口,其中Factory2是Factory的子接口,都只有唯一一个onCreateView方法。

不同之处在于Factory2的onCreateView方法传入了parentView。

该方法的作用就是你可以借助它来改造XML中已经存在了的Tag的值。所以Factory2可以达到改造parentView的目的。

但是我们在日常中根本就没有任何地方接触到了Factory(2)呀,那么它是不是就直接是null呢?

到这里又是一番源码调来调去,为了便于理解,只需要知道,这个东西(Factory2),在最开始AppCompatActivity(为了兼容低版本,我们现在Activity默认都是继承自它)中的onCreate方法中就已经通过层层调用被设置好了。

既然现在Factory2不为空,那么就应该去走它的onCreateView方法了,这里又是层层调用,最终来到了AppCompatViewInflater**** 的 createView 方法:

答案就在这里:

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

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

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

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

学习分享,共勉

Android高级架构师进阶之路

题外话,我在阿里工作多年,深知技术改革和创新的方向,Android开发以其美观、快速、高效、开放等优势迅速俘获人心,但很多Android兴趣爱好者所需的进阶学习资料确实不太系统,完整。今天我把我搜集和整理的这份学习资料分享给有需要的人

  • Android进阶知识体系学习脑图

  • Android进阶高级工程师学习全套手册

  • 对标Android阿里P7,年薪50w+学习视频

  • 大厂内部Android高频面试题,以及面试经历

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

[外链图片转存中…(img-6A8hFQTb-1712610761003)]

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

  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值