1、Android 补间动画和属性动画的区别?
补间动画仅仅对画布操作,新位置并不响应点击事件,原位置响应。属性动画是通过修改view属性实现动画,新位置响应点击事件
2、Window和DecorView是什么?DecorView又是如何和Window建立联系的?
Window
是 WindowManager
最顶层的视图,它负责背景(窗口背景)、Title之类的标准的UI元素,Window
是一个抽象类,整个Android系统中, PhoneWindow
是 Window
的唯一实现类。至于 DecorView
,它是一个顶级 View
,内部会包含一个竖直方向的LinearLayout
,这个 LinearLayout
有上下两部分,分为 titlebar 和 contentParent 两个子元素,contentParent 的 id 是 content,而我们自定义的 Activity
的布局就是 contentParent 里面的一个子元素。 View
层的所有事件都要先经过 DecorView
后才传递给我的 View
。 DecorView
是 Window
的一个变量,即 DecorView
作为一切视图的根布局,被 Window
所持有,我们自定义的 View 会被添加到 DecorView
,而DecorView
又会被添加到 Window
中加载和渲染显示。
此处放一张它们的简单内部层次结构图:
3、简述一下 Android 中 UI 的刷新机制?
界面刷新的本质流程
- 通过
ViewRootImpl
的scheduleTraversals()
进行界面的三大流程。- 调用到
scheduleTraversals()
时不会立即执行,而是将该操作保存到待执行队列
中。并给底层的刷新信号注册监听。- 当
VSYNC
信号到来时,会从待执行队列
中取出对应的scheduleTraversals()
操作,并将其加入到主线程
的消息队列中
。主线程
从消息队列中
取出并执行三大流程: onMeasure()-onLayout()-onDraw()
同步屏障的作用
同步屏障
用于阻塞
住所有的同步消息
(底层VSYNC的回调onVsync方法提交的消息是异步消息
)- 用于保证
界面刷新功能的performTraversals()
的优先执行。
同步屏障的原理?
- 主线程的
Looper
会一直循环调用MessageQueue
的next
方法并且取出队列头部的Message
执行,遇到同步屏障(一种特殊消息)
后会去寻找异步消息
执行。如果没有找到异步消息
就会一直阻塞下去,除非将同步屏障
取出,否则永远不会执行同步消息
。- 界面刷新操作是异步消息,具有最高优先级
- 我们发送的消息是同步消息,再多耗时操作也不会影响UI的刷新操作
4、LinearLayout, FrameLayout, RelativeLayout 哪个效率高, 为什么?
对于比较三者的效率那肯定是要在相同布局条件下比较绘制的流畅度及绘制过程,在这里流畅度不好表达,并且受其他外部因素干扰比较多,比如CPU、GPU等等,我说下在绘制过程中的比较,
1、Fragment是从上到下的一个堆叠的方式布局的,那当然是绘制速度最快,只需要将本身绘制出来即可,但是由于它的绘制方式导致在复杂场景中直接是不能使用的,所以工作效率来说Fragment仅使用于单一场景,
2、LinearLayout 在两个方向上绘制的布局,在工作中使用页比较多,绘制的时候只需要按照指定的方向绘制,绘制效率比Fragment要慢,但使用场景比较多,
3、RelativeLayout 它的没个子控件都是需要相对的其他控件来计算,按照View树的绘制流程、在不同的分支上要进行计算相对应的位置,绘制效率最低,但是一般工作中的布局使用较多,所以说这三者之间效率分开来讲个有优势、不足,那一起来讲也是有优势、不足,所以不能绝对的区分三者的效率。
5、谈谈Android的事件分发机制?
1.触发过程:Activity->Window->DocerView->ViewGroup->View,View不触发再返回由父级处理依次向上推。
2.在每个阶段都要经过三个方法 dispatchTouchEvent(分发)、onInterceptTouchEvent(拦截)、onTouch(处理)
大体流程:
Activity中走了Window 的 dispatch,Window 的 dispatch 方法直接走了 DocerView 的 dispatch 方法,DocerView 又直接分发给了 ViewGroup,ViewGroup 中走的是 onInterce 判断是否拦截,拦截的话会走 onTouch 来处理,不拦截则继续下发给 View。到 View 这里已经是最底层了,View 若继续不处理,那就调用上层的 onTouch 处理,上层不处理继续往上推。
6、针对RecyclerView做了哪些优化?
RecyclerView作为android的重要View,有很大的灵活性,可以替代ListView GridView ScrollView,所以需要深入了解一下Rv的性能以及如何去处理优化,实现更加流畅体验,这点是毋庸置疑的,所谓的RV优化其实也是对适配器以及刷新数据的,还有资源复用的优化。
1 .onBindViewHolder
这个方法含义应该都知道是绑定数据,并且是在UI线程,所以要尽量在这个方法中少做一些业务处理
2. 数据优化
采用android Support 包下的DIffUtil集合工具类结合RV分页加载会更加友好,节省性能
3.减少item的View的层级,(pps:当然推荐把一个item自定义成一个View,如果有能力的话),如果item的高度固定的话可以设置setHasFixedSize(true),避免requestLayout浪费资源
4 .使用RecycledViewPool
RecycledViewPool是对item进行缓存的,item相同的不同RV可以才使用这种方式进行性能提升
5. 通过重写RecyclerView.onViewRecycled(holder)来合理的回收资源。
6.分页加载
7.有大量图片时,滚动停止加载图片,停止才通知adapter去加载
7、谈一谈获取View宽高的几种方法?
1.OnGlobalLayoutListener获取
2.OnPreDrawListener获取
3.OnLayoutChangeListener获取
4.重写View的onSizeChanged()
5.使用View.post()方法
8、View.post()为什么可以获取到宽高信息?
View.post方法调用时,如果在 View 还没开始绘制时( Activity 的 onResume方法还没回调之前 或者onResume方法执行了,但是 ViewRootImpl 的 performTraversals 还没开始执行)就会用一个初始长度为 4 的数组缓存起来(Runnable 数量大于4时会进行扩容),ViewRootImpl 在初始化时创建了一个 View.AttchInfo 对象并绑定 ViewRootImpl 的 Handler ,该 Handler 也用于发送 View 绘制相关的 msg ;
等到 ViewRootImpl执行 performTraversals方法时(此时 Activity 已经回调了onResume),会配置 View 的 AttchInfo 对象并且通过 View 的 dispatchAttachedToWindow 方法传入到 View 里面完成绑定,在该方法中会取出 View 缓存的 Runnable 并用 View.AttchInfo 的 Handler 来进行 post 方法,这样子就会加入到 MessageQueue 里面进行排队,等到这些缓存 Runnable 执行时,主线程里面 View的绘制流程也就结束了,所以这时候 Looper 取出这些缓存的Runnable 执行时就可以拿到 View 的宽高
那么,什么情况下View.post 方法不会执行呢?如果 Activity 因为某些原因没有执行到 onResume 的话,无法顺利调用 ViewRootImpl 的 performTraversals 的话,View.post 方法就不会执行
9、谈一谈插值器和估值器?
1、插值器,根据时间(动画时常)流逝的百分比来计算属性变化的百分比。系统默认的有匀速,加减速,减速插值器。
2、估值器,通过上面插值器得到的百分比计算出具体变化的值。系统默认的有整型,浮点型,颜色估值器
3、自定义只需要重写他们的evaluate方法就可以了。
10、有用过ConstraintLayout吗?它有哪些特点?
性能上的优化 减少布局嵌套的问题
特点有
1,相对定位
2,尺寸约束
3,边距设置
4,角度设置
5,宽高占比
6,居中