| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 移动开发 -> Android面试官:,Android面试必问 -> 正文阅读 |
|
[移动开发]Android面试官:,Android面试必问 |
相比 Viewgroup 和 View,ViewRootImpl 可能更为陌生,实际开发中我们基本用不到它。那么
从结构上来看,ViewRootImpl 和 ViewGroup 其实是一种东西 它们都继承了 ViewParent。ViewParent 是一个接口,定义了一些父 View 的基本行为,比如 requestlayout,getparent 等。不同的是,ViewRootImpl 并不会像 ViewGroup 一样被真正绘制在屏幕上。在 activity 中,它是专门用来绘制 DecorView 的,核心方法是 setView 提到 DecorView,就不得不说一下 window 了。面试中常常我们提到一个点,或者一个词,面试官会马上引申出这个知识点相关的问题。如果我们只是死记硬背,自顾自背一堆绘制相关的东西而回答不上来,会大大减分。所以储备与必问内容相关的东西对面试和自己的知识体系很有帮助。不少老爷被面试的时候都会被问到一个问题
我们可以通过一张图来说明。 如图所示,window 是 activity 里的一个实例变量,本质是一个接口,唯一的实现类是 PhoneWindow。 activity 的 setContentView 方法实际上是就是交给 phonewindow 去做的。window 和 View 的关系可以类比为显示器和显示的内容。 每个 activity 都有一个“显示器” window,“显示的内容”就是 DecorView。这个“显示器”定义了一些方法来决定如何显示内容。比如 setTitleColor setTitle 是设置导航栏的颜色和 title , setAllowReturnTransitionOverlap 设置进/出场动画等等。 所以 window 是 activity 的一个成员变量,window 和 View 是“显示器”和“显示内容”的关系。 这就是他们的关系
在整个 activity 的生命周期中,setContentView 是在 onCreate 中调用的,它实现了对资源文件的解析,完成了 xml 文件到 View 的转化。那么 View 真正开始绘制是在哪个生命周期呢?
他们的关系在源码中一目了然。 从源码中可以看到,onResume 之后,ActivityThread 通过调用 activity 中 windowmanager 的 addView 方法,将 decorView 传入到 ViewRootImpl 的 setView 方法中,通过 setView 来完成 View 的绘制。 问题又来了,setView 到底有什么魔法,为什么他就能完成 View 的绘制工作呢? 我们再来看一下 setView 方法 简单来说 setView 做了三件事 ① 检查绘制的线程是不是创建 View 的线程。这里可以引申出一个问题,View 的绘制必须在主线程吗? ② 通过内存屏障保证绘制 View 的任务是最优先的 ③ 调用 performTraversals 完成 measure,layout,draw 的绘制 看到这里,ViewRootImpl 的绘制基本就完成了。其实这也是面试官希望听到的内容。考察的是面试者对 View 绘制体系的理解。 后续 ViewGroup 和 View 的绘制其实是 performTraversals 对整个 ViewTree 的绘制。他们的关系可以用下面这张图表示
这个问题乍看挺唬人的。其实看一眼源码大概就明白了 View.post 会判断当前 View 是否已经被添加到 window 上。如果添加了则立即执行 runnable,如果没有被添加则先放到一个队列中存储起来,等添加到 window 上时再执行。 而 View 被测量完成后才会 attachToWindow。所以当 post 的 runnable 执行时,View 已经绘制完成了。
这个问题看似很简单死板,其实是想考察对 View 测量的理解。 View 的大小不仅仅取决于自身的宽高,还取决于父 View 的大小和测量模式。一个 200_200 的父 View 是不可能容纳一个 300_300 的子 View 的,父 View 的 wrap_content 和 match_content 也会影响子 View 的大小。 所以 View 的 measure 函数其实应该有 4 个参数:父 View 的宽,父 View 的高,宽的测量模式,高的测量模式。 Android 这里用了一个巧妙的设计,用一个 Int 值来表示宽/高的测量模式和大小。一个 int 有 32 位,前 2 位表示测量 MODE,后 30 位表示 SIZE。 为什么要用 2 位表示 MODE 呢?因为 MODE 只有 3 种呀,UNSPECIFIED,EXACTLY,AT_MOST,小傻瓜。 |
|
移动开发 最新文章 |
Vue3装载axios和element-ui |
android adb cmd |
【xcode】Xcode常用快捷键与技巧 |
Android开发中的线程池使用 |
Java 和 Android 的 Base64 |
Android 测试文字编码格式 |
微信小程序支付 |
安卓权限记录 |
知乎之自动养号 |
【Android Jetpack】DataStore |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/23 16:37:01- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |