面试 100% 完全掌握:重新认识 View 的绘制流程,2024年最新android高级面试题pdf

  1. 调用requestLayout 和 invalidate标记绘制和充布局信息

  2. Choreographer接受系统垂直同步等脉冲消息,在scheduleTraversals方法中回调执行doTraversal 开始遍历view树。

  3. 触发ViewRootImpl#performTraversals完成view树遍历

  4. 如果layoutRequested 为true,measureHierarchy 中测量 mView 及其子view

  5. 需要的话,触发ViewRootImpl#performLayout 完成布局

  6. 如果view没有隐藏且TreeObserver中没有拦截绘制,就调用performDraw,完成绘制

  7. 计算dirty脏区域

  8. 从mSurface中 获取脏区域的canvas,交给view绘制

2.2 ViewRootImpl 创建时机


从上面可以看到,所有的绘制和布局都是由ViewRootImpl#doTraversal触发,然后对其持有的view树进行遍历绘制。所以一定要了解ViewRootImpl和其持有的DecorView的创建和关联时机。关键流程如下:

  1. Activity#handleResume 的时候,调用WIndowManager#addView添加decorView

  2. 调用到WindowManagerGlobal#addView 的时候创建ViewRootImpl实例。

  3. 调用ViewRootImpl#setView完成一系列初始化方法

  4. 注册mDisplayListener 到DisplayManager,接收显示更新回调

  5. 调用 requestLayout 更新一次布局大小和位置信,以确保从系统接收任何其他事件之前进行过一次布局

  6. 通过WindowSession 调用addToDisplayAsUser,添加window

  7. 在接收系统事件的时候,调用scheduleTraversals 绘制view树

WindowMangerGlobal 最终调用的其实都是ViewRootImpl方法。ViewRootImpl在addView关联号DecorView后,还调用了setView方法进行初始化,接收垂直同步脉冲信息,代码如下:

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,

int userId) {

mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);

// Schedule the first layout -before- adding to the window

// manager, to make sure we do the relayout before receiving

// any other events from the system.

requestLayout();

try{

res = mWindowSession.addToDisplayAsUser(mWindow, mSeq, mWindowAttributes,

getHostVisibility(), mDisplay.getDisplayId(), userId, mTmpFrame,

mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,

mAttachInfo.mDisplayCutout, inputChannel,

}

}

在初始化的最后,通过WindowSession 调用addToDisplayAsUser添加了window到屏幕显示中。

三. 附加contentView到界面

===================

当我们启动activity,将我们写的xml布局文件显示在屏幕上,其中经历了那些过程呢?我们要在界面上展示内容,有如下几个步骤:

  1. 启动activity,在performLaunchActivity的时候创建Activity并且attach和调用onCreate方法

  2. 在attach的时候,创建PhoneWindow实例并持有mWindow引用

  3. 调用setContentView 以附加内容到windows中

  4. 通过确认decorView 以及 subDecorView存在,创建DecorViewsubDecorView

  5. 添加ContentViewdecorView树中的 R.id.content节点

  6. handleResumeActivity的时候,调用WindowManager.addView。关联ViewViewRootImpl,后续便可以绘制。

3.1 创建PhoneWindow


我们先看启动activity的方法,ActivityThread#performLaunchAcivity。 从该方法源码中可知,启动activity的方法流程如下:

  1. 创建Activity实例 ,在Instrumentation#newActivity完成

  2. 创建PhoneWindows附加到Activity。在Activity#attachAcitivity完成

  3. 调用Activity的onCreate生命周期,代码是Instrumentation#callActivityOnCreate

  4. onCreate中执行用户自定义的代码,比如setContentView

所以可知,在activity准备启动的时候,就已经完成了PhoneWindows实例的创建。而接下来就执行到了我们在Activity#onCreate中调用setContentView方法设置的自定义布局。

3.2 setContentView的本质


activity在启动之后,我们通常在onCreate调用setContentView中设置自己的布局文件。我们来具体看看setContentView做了什么。 setContentView方法本质其实是向android.R.id.content添加自己。 我们看AppCompatDelegateImpl#setContentView

@Override

public void setContentView(View v, ViewGroup.LayoutParams lp) {

///确认好 window decorView 以及 subDecorView

ensureSubDecor();

//向 android.R.id.content 添contentView

ViewGroup contentParent = mSubDecor.findViewById(android.R.id.content);

contentParent.removeAllViews();

contentParent.addView(v, lp);

mAppCompatWindowCallback.getWrapped().onContentChanged();

}

这一块代码关键在于向id为android.R.id.content的子view中添加contentView。 addView的过程自然会触发布局的重新渲染。 关键之处还是在于ensureSubDecor()方法中对于decoView 以及subDecorView的实例化创建工作。

3.3 确认window ,decorView 以及 subDecorView


先看看AppCompatDelegateImpl#ensureSubDecor()的主要实现:

private void ensureSubDecor() {

if (!mSubDecorInstalled) {

mSubDecor = createSubDecor();

}

}

private ViewGroup createSubDecor() {

// Now let’s make sure that the Window has installed its decor by retrieving it

ensureWindow();

mWindow.getDecorView();

final LayoutInflater inflater = LayoutInflater.from(mContext);

ViewGroup subDecor = null;

//省略其他样式subDecor布局的实例化

//包含 actionBar floatTitle ActionMode等样式

subDecor = (ViewGroup) inflater.inflate(R.layout.abc_screen_simple, null);

//省略状态栏适配代码

//省略actionBar布局替换代码

mWindow.setContentView(subDecor);

return subDecor;

}

代码很长,上面是经过省略之后的主要代码。可以看到代码逻辑很清晰:

  • 步骤一:确认window并attach(设置背景等操作)

  • 步骤二:获取DecorView,因为是第一次调用所以会installDecor(创建DecorView和Window#ContentLyout)

  • 步骤三:从xml中实例化出subDecor布局

  • 步骤四:设置内容布局: mWindow.setContentView(subDecor);

3.4 初始化 installDecor


关键两处代码是Window#installDecor 和 Window#setContentView。 先看一下Window#installDecor的代码:

private void installDecor() {

mForceDecorInstall = false;

mDecor = generateDecor(-1);

if (mContentParent == null) {

//R.id.content

mContentParent = generateLayout(mDecor);

final decorContentParent = (DecorContentParent) mDecor.findViewById(

R.id.decor_content_parent);

if (decorContentParent != null) {

//…省略一些decorContentParent的处理

} else {

mTitleView = findViewById(R.id.title);

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

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

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

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

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

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

总结

【Android 详细知识点思维脑图(技能树)】

image

其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

虽然 Android 没有前几年火热了,已经过去了会四大组件就能找到高薪职位的时代了。这只能说明 Android 中级以下的岗位饱和了,现在高级工程师还是比较缺少的,很多高级职位给的薪资真的特别高(钱多也不一定能找到合适的),所以努力让自己成为高级工程师才是最重要的。

这里附上上述的面试题相关的几十套字节跳动,京东,小米,腾讯、头条、阿里、美团等公司19年的面试题。把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节。

由于篇幅有限,这里以图片的形式给大家展示一小部分。

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

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
img
(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节。

由于篇幅有限,这里以图片的形式给大家展示一小部分。

[外链图片转存中…(img-0Z5FXABE-1712775570699)]

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

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

  • 15
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当涉及到Android面试时,高级级别的问通常会涉及更深入的主和技术。以下是一些可能的高级Android面试及其答案: 1. 请解释一下Android中的四大组件。 答:Android中的四大组件是Activity、Service、BroadcastReceiver和ContentProvider。Activity用于用户界面的展示和交互,Service用于在后台执行长时间运行的任务,BroadcastReceiver用于接收和处理系统广播消息,ContentProvider用于数据共享和访问。 2. 请解释一下Android中的MVC、MVP和MVVM架构模式。 答:MVC(Model-View-Controller)是一种软件设计模式,将应用程序分为模型(数据)、视图(用户界面)和控制器(逻辑处理)三个部分。MVP(Model-View-Presenter)是MVC的变体,将控制器替换为Presenter,使视图和模型之间的耦合更低。MVVM(Model-View-ViewModel)是一种新的架构模式,通过数据绑定实现视图和模型之间的通信。 3. 请解释一下Android中的内存泄漏以及如何避免。 答:内存泄漏是指应用程序中未使用的内存无法被垃圾回收器回收,导致内存占用不断增加。在Android中,常见的内存泄漏原因包括静态引用、匿名内部类、Handler引起的内存泄漏等。避免内存泄漏的方法包括及时释放资源、避免使用静态引用、避免匿名内部类等。 4. 请解释一下Android中的线程和线程间通信方式。 答:在Android中,可以使用Thread类或者HandlerThread类创建线程。线程间通信的方式包括使用Handler进行消息传递、使用AsyncTask进行异步任务处理、使用BroadcastReceiver进行广播消息传递等。 5. 请解释一下Android中的性能优化技巧。 答:Android性能优化的技巧包括减少内存使用、优化布局和绘制、使用合适的数据结构和算法、避免频繁的IO操作、使用缓存等。此外,还可以使用工具如Lint、TraceView和HierarchyViewer进行性能分析和调优。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值