最全面试官:说说Android-fragment-标签加载过程;我:------,这份字节跳动历年校招Android面试真题解析

面试宝典

面试必问知识点、BATJ历年历年面试真题+解析

学习经验总结

(一)调整好心态
心态是一个人能否成功的关键,如果不调整好自己的心态,是很难静下心来学习的,尤其是现在这么浮躁的社会,大部分的程序员的现状就是三点一线,感觉很累,一些大龄的程序员更多的会感到焦虑,而且随着年龄的增长,这种焦虑感会越来越强烈,那么唯一的解决办法就是调整好自己的心态,要做到自信、年轻、勤奋。这样的调整,一方面对自己学习有帮助,另一方面让自己应对面试更从容,更顺利。

(二)时间挤一挤,制定好计划
一旦下定决心要提升自己,那么再忙的情况下也要每天挤一挤时间,切记不可“两天打渔三天晒网”。另外,制定好学习计划也是很有必要的,有逻辑有条理的复习,先查漏补缺,然后再系统复习,这样才能够做到事半功倍,效果才会立竿见影。

(三)不断学习技术知识,更新自己的知识储备
对于一名程序员来说,技术知识方面是非常重要的,可以说是重中之重。**要面试大厂,自己的知识储备一定要非常丰富,若缺胳膊少腿,别说在实际工作当中,光是面试这一关就过不了。**对于技术方面,首先基础知识一定要扎实,包括自己方向的语言基础、计算机基础、算法以及编程等等。

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

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

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

这个 layout 文件是相对特殊的,因为这个 fragment 标签不是很常见,而且大家回忆下 LayoutInflater 的 inflate 流程,其中 inflate 方法的返回值是 View。而我们看下 Fragment 的定义:

public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener {
}

可以看到 Fragment 并不是一个 View,那说明 fragment 标签就不是通过正常的反射来创建的,进一步说就是 fragment 标签的创建和普通的 view 不是一个流程。

2、思考

问题:既然 fragment 标签的创建和普通的 view 不是一个流程,那 fragment 标签是怎么加载的呢?

首先我们想下前提条件:fragment 标签仍然是处于布局文件中的。就是说 fragment 标签节点也会被 LayoutInflater 解析,只是被解析之后的流程和别的 view 不一样了。一路跟踪流程,我们来到了 LayoutInflater 的 createViewFromTag 方法:

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) {
view = mPrivateFactory.onCreateView(parent, name, context, attrs);
}

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

我贴出来这段代码是为了总结下通过 setContentView 这种方式创建出 View 的途径:

  1. Factory2.onCreateView;
  2. Factory.onCreateView;
  3. mPrivateFactory.onCreateView;
  4. createView;

其中1、2、4方式相信看过前面几篇文章的小伙伴肯定都很熟悉了:

  • 1、2两种方式本质上一样,可以通过我们自己设置的 Factory 来创建View;
  • 4这种方式是通过反射来创建 View对象;
  • 而方式3在之前的几篇文章中则没有说到过,不过别急,接下来我们会介绍它;

到了这里我们知道通过 setContentView 这种方式创建出 View 的途径有4种,其中第4种我们直接排除掉了,也就只剩下了前三种方式。

3、探究

在我们探索究竟是这三种方式中的哪一种之前,我们先来熟悉下 mPrivateFactory。我们看下它的定义及设值的地方:

private Factory2 mPrivateFactory;// 定义可以看出 mPrivateFactory 也实现了 Factory2

protected LayoutInflater(LayoutInflater original, Context newContext) {
mContext = newContext;
mFactory = original.mFactory;
mFactory2 = original.mFactory2;
mPrivateFactory = original.mPrivateFactory;
setFilter(original.mFilter);
}

/**

  • @hide for use by framework
    */
    public void setPrivateFactory(Factory2 factory) {
    if (mPrivateFactory == null) {
    mPrivateFactory = factory;
    } else {
    mPrivateFactory = new FactoryMerger(factory, factory, mPrivateFactory, mPrivateFactory);
    }
    }

我们就知道了 mPrivateFactory 实现了 Factory2 接口,设值方式有两种,一种是 framework 调用,还有一种是创建 LayoutInflater 的时候传入。

这三种方式有一个共同特点就是都和 Factory 相关。而使用 Factory 都会通过 LayoutInflater setFactory,既然我们没有做事情就完成了对 fragment 标签的解析,那有理由相信是系统处理了。使用 Fragment 的时候需要继承 FragmentActivity 或者是 AppCompatActivity,这里就以 FragmentActivity 为例来分析,来搜下哪里调用了 setFactory 函数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

但是在 FragmentActivity 的继承链上的各个类我们并没有搜到 setFactory 或 setFactory2。这两个常规的设置没有找到,我们再来找第三种方式 setPrivateFactory,最终在 Activity 搜到了,attach 方法中:

mWindow.getLayoutInflater().setPrivateFactory(this);

然后我们看下 Activity 的定义,实现了 LayoutInflater.Factory2 接口

public class Activity extends ContextThemeWrapper
implements LayoutInflater.Factory2,
Window.Callback, KeyEvent.Callback,
OnCreateContextMenuListener, ComponentCallbacks2,
Window.OnWindowDismissedCallback, WindowControllerCallback,
AutofillManager.AutofillClient {

@Nullable
public View onCreateView(String name, Context context, AttributeSet attrs) {
return null;
}

public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
if (!“fragment”.equals(name)) {
return onCreateView(name, context, attrs);
}

return mFragments.onCreateView(parent, name, context, attrs);
}

}

可以看出来在 onCreateView 方法中会判断标签名字如果是 fragment 的话则会调用 mFragments.onCreateView 来创建 View。

接下来总结下流程:

  1. 在 Activity 的 attach 方法中会为当前 Activity 的设置 mPrivateFactory;
  2. 在 LayoutInflater 的 createViewFromTag 方法中会先使用 Factory2 或 Factory 来创建view;
  3. 针对 fragment 的场景下默认获取到的 view 是null;
  4. 如果是 null 则通过 mPrivateFactory 创建 view,这里就会走到 Activity 的onCreateView 方法;
  5. 通过 mFragments(也就是 FragmentController)的 onCreateView 方法来创建 View;

4、mFragments.onCreateView

mFragments 其实是 FragmentController,然后细跟代码会走到 FragmentManager 的 onCreateView 方法:

@Override
public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
if (!“fragment”.equals(name)) {
return null;
}

moveToState(fragment, Fragment.CREATED, 0, 0, false);

if (fragment.mView == null) {
throw new IllegalStateException("Fragment " + fname

  • " did not create a view.");
    }
    return fragment.mView;
    }

然后到了 moveToState 方法,注意传入的 newState 是 Fragment.CREATED。

最后

说一千道一万,不如自己去行动。要想在移动互联网的下半场是自己占有一席之地,那就得从现在开始,从今天开始,马上严格要求自己,既重视业务实现能力,也重视基础和原理。基础夯实好了,高楼才能够平地而起,稳如泰山。

最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的24套腾讯、字节跳动、阿里、百度2020-2021面试真题解析,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节

还有 高级架构技术进阶脑图、Android开发面试专题资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

一线互联网面试专题

379页的Android进阶知识大全

379页的Android进阶知识大全

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

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

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

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

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值