【面试必备】Android UI 绘制相关面试整理

本文详细讨论了Android中的关键概念和技术,包括补间动画与属性动画的区别,Window和DecorView的关系及其在UI层次结构中的作用,AndroidUI的刷新机制,以及LinearLayout、FrameLayout和RelativeLayout的效率比较。此外,还涵盖了事件分发机制,RecyclerView和ListView的优化策略,RemoteViews的使用场景,获取View尺寸的方法,以及插值器和估值器在动画中的角色。同时,解释了LayoutInflater如何通过inflate方法创建View,并概述了RecyclerView的缓存机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、Android 补间动画和属性动画的区别?

alt
alt

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等等,我说下在绘制过程中的比较

  • Fragment是从上到下的一个堆 叠的方式布局的,那当然是绘制速度最快,只需要将本身绘制出来即可,但是由于它的绘制方式导致在复杂场景中直接是不能使用的,所以工作效率来说Fragment仅使用于 单一场景
  • LinearLayout 在两个方向上绘制的布局,在工作中使用页比较多,绘制的时候只需要按照指定的方向绘制,绘制效率比Fragment要慢,但使用场景比较多,
  • RelativeLayout 它的没个子控件都是需要相对的其他控件来计算,按照View树的绘制流程、在不同的分支上要进行计算相对应的位置,绘制效率最低,但是一般工作中的 布局使用较多,所以说这三者之间效率分开来讲个有优势、不足,那一起来讲也是有优势、不足,所以不能绝对的区分三者的效率

5、谈谈Android的事件分发机制?

当点击的时候,会先调用顶级viewgroup的dispatchTouchEvent,如果顶级的viewgroup拦截了此事件
(onInterceptTouchEvent返回true),则此事件序列 由顶级viewgroup处理。如果顶级viewgroup设置
setOnTouchListener,则会回调接口中的onTouch,此时顶级的viewgroup中的onTouchEvent不再回调,如果不设 置
setOnTouchListener则onTouchEvent会回调。如果顶级viewgroup设置setOnClickListener,则会回调接口中的
onClick。如果顶级viewgroup不拦截事件,事件就会向下传递给他的子view,然后子view就会调用它的
dispatchTouchEvent方法。

6、针对RecyclerView你做了哪些优化?

  • onBindViewHolder.
    这个方法含义应该都知道是绑定数据,并且是在UI线程,所以要尽量在这个方法中少做一些业务处理
  • 数据优化.
    采用androidSupport 包下的DIffUtil集合工具类结合RV分页加载会更加友好,节省性能
  • item优化.
    减少item的View的层级,(pps:当然推荐把一个item自定义成一个View,如果有能力的话),如果item的高度固定的话可以设置setHasFixedSize(true),避免requestLayout浪费资源
  • 使用RecycledViewPool.
    RecycledViewPool是对item进行缓存的,item相同的不同RV可以才使用这种方式进行性能提升
  • Prefetch预取.这是在RV25.1.0及以上添加的新功能,预取详情资源回收.
    过重写RecyclerView.onViewRecycled(holder)来合理的回收资源

7、谈谈如何优化ListView?

ViewHolder什么的持有View预加载/懒加载数据什么的
大招:用RecyclerView替换ListView 绝招:直接删除控件

8、谈谈自定义LayoutManager的流程?

  • 确定Itemview的LayoutParamsgenerateDefaultLayoutParams
  • 确定所有itemview在recyclerview的位置,并且回收和复 用itemviewonLayoutChildren
  • 添加滑动canScrollVertically

9、什么是 RemoteViews?使用场景有哪些?

RemoteViews翻译过来就是远程视图.顾名思义,RemoteViews不是当前进程的View,是属于SystemServer进程.应用程序与RemoteViews之间依赖Binder实现了进程间通信.

用法:通常是在通知栏

> //1.创建RemoteViews实例
> RemoteViews mRemoteViews=new
> RemoteViews("com.example.remoteviewdemo", R.layout.remoteview_layout);
> //2.构建一个打开Activity的PendingIntent Intent
> intent=new
> Intent(MainActivity.this,MainActivity.class);
> PendingIntent
> mPendingIntent=PendingIntent.getActivity(Main
> Activity.this, 0, intent,
> PendingIntent.FLAG_UPDATE_CURRENT);
> //3.创建一个Notification
> mNotification = new
> Notification.Builder(this)
> .setSmallIcon(R.drawable.ic_launcher)
> .setContentIntent(mPendingIntent)
> .setContent(mRemoteViews)
> .build();
> //4. 获 取 NotificationManager
> manager = (NotificationManager)
> getSystemService(Context.NOTIFICATION_SERVICE
> );
> Button button1 = (Button)
> findViewById(R.id.button1);
> button1.setOnClickListener(new
> OnClickListener() {
> @Override
> public void onClick(View v) {
> //弹出通知
> manager.notify(1, mNotification);
> }
> });

10、谈一谈获取View宽高的几种方法?

  • OnGlobalLayoutListener获取
  • OnPreDrawListener获取
  • OnLayoutChangeListener获取
  • 重写View的onSizeChanged()
  • 使用View.post()方法

11、谈一谈插值器和估值器?

  • 插值器,根据时间(动画时常)流逝的百分比来计算属
    性变化的百分比。系统默认的有匀速,加减速,减速插值器。
  • 估值器,通过上面插值器得到的百分比计算出具体变化
    的值。系统默认的有整型,浮点型,颜色估值器
  • 自定义只需要重写他们的evaluate方法就可以了。

12、getDimension、getDimensionPixelOffset 和getDimensionPixelSize 三者的区别?

相同点:单位为dp/sp时,都会乘以density,单位为px则不乘

不同点:

  • getDimension返回的是float值
  • getDimensionPixelSize,返回的是int值,float转成int时,四舍五入
  • getDimensionPixelOffset,返回的是int值,float转int时,向下取整(即忽略小数值)

13、关于LayoutInflater,它是如何通过inflate 方法获取到具体View的?

系统通过LayoutInflater.from创建出布局构造器,inflate 方法中,最后会掉用createViewFromTag这里他会去判断两个参数factory2 和factory 如果都会空就会系统自己去创建view, 并且通过一个xml解析器,获取标签名字,然后判断是<Button还是xxx.xxx.xxView.然后走createView通过拼接得到全类名路径,反射创建出类。

14、谈谈RecyclerView的缓存机制?

scrap viewCacherecyclerPool:
scrap 是当前展示的缓存, 在onlayout时候 缓存viewCache 是屏幕外看不见的缓存, 可以吧viewCache设置大点, 空间换时间 避免段距离内快速滑动卡顿以上两种缓存是不走 createView和 onbind recyclerPool 比较特殊他是会走 onbind的,他可以被多个recyclerView共享内部的item,实际用途是:多个recyclerView之间共享item,应用在 垂直recyclerView 内嵌水平recyclerView,或者viewpager中多个recyclerView

下面为了帮助大家准备面试,免费分享由八年安卓大佬整理的2023最新Android大厂高频面试题解析大全》,扫码获取!!

[2023最新Android大厂高频面试题解析大全]

第一章 Android 相关

在这里插入图片描述

第二章 性能优化

在这里插入图片描述

第三章 Java 相关

在这里插入图片描述

第四章 Kotlin 相关

在这里插入图片描述

第五章 网络相关

在这里插入图片描述

第六章 插件化&热修复&模块化&组件化

在这里插入图片描述

第七章 图片相关

在这里插入图片描述

第八章 Flutter 相关

在这里插入图片描述

有需要文中资料的朋友们可以扫码免费领取哦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值