oppo android面试,阿里技术团队整理(1),字节面试官

Total frames rendered: 2245

Janky frames: 31 (1.38%)

50th percentile: 5ms

90th percentile: 10ms

95th percentile: 14ms

99th percentile: 18ms

然而以上工具和指标定义在 app 的复杂场景下,尚存在问题

  1. 多平台问题

现 APP 技术有原生、h5、小程序、RN、weex、flutter 等。暂无一款无侵入的流畅度检测工具能同时支持多个平台、多种机型和多个指标数据,而侵入式的检测工具无法检测竞品 APP。

  1. 指标选择和用户体验一致性

我们期望能有少量的几个指标数据,准确的表达用户流畅度体感。

平均 FPS(SM 和 SF 类似),不足以反映用户体验。如相同 30 FPS,可以是 1s 内 30 个 33.3 ms的画面,也可以是 29 个 16.6ms 的画面再加 1 个 516.9 ms 的画面,但用户体验并不相同。

  1. 流畅度数据影响因素多

滑动速度和滑动状态:idle(停止)、drag(手指拖拽)、fling(自由滑动)都是影响流畅度数据的重要因素。

2.2 流畅度指标制定

维基百科 动画定义:一种通过定时拍摄一系列多个静止的固态图像(帧)以一定频率连续变化、运动(播放)的速度(如每秒16张)而导致肉眼的视觉残象产生的错觉——而误以为图画或物体(画面)活动的作品及其影片技术。

列表滑动同理,是 APP 以一定频率(60hz下16.6ms)和不同 offset 计算出一系列静止画面,让肉眼看到滑动动画。

当我们说列表滑动不流畅,是因为频率过低无法让肉眼产生视觉残留,或在时间(画面停留时长)和空间(画面内容)产生跳变,让用户感知到变化的不自然。以此我们可以定义指标如下:

  • 时间角度

  • 定义平均 FPS:定义一次检测的平均帧率。反应画面平均停留时长。

  • 定义 1s 大卡顿次数:平均 1s 内出现占用 3 帧及以上的画面次数。反应画面停留时长跳变

  • 空间角度

  • offset 跳变值:在画面不掉帧的情况,若其中一个画面出现跳变,甚至花屏或者绿屏会让用户体验到不流畅。在 APP 滑动过程中,画面内容由 offset 决定,而 offset 跳变,和卡顿时长、差值器实现均有关联,现有差值器实现基本基于 D/T 曲线(距离/时间),为此平均 FPS 和 1s 大卡顿次数很大程度上体现了画面跳变,同时考虑到无侵入式检测 offset 的难度问题,暂不考虑 offset 跳变值。

综上,我们定义流畅度指标为平均 FPS 值和 1s 大卡顿次数。

2.3 流畅度检测工具实现

我们从 APP 录屏画面入手,计算流畅度指标值。当我们得到 APP 滑动过程中的录屏数据,可通过每 16.6ms 检测录屏画面是否发生变化,当连续画面未发生变化,则表示发生了卡顿。无变化的连续画面数则表示了卡顿的时长。

为得到目标 APP 录屏数据,检测工具 APP 向系统注册录屏服务,然后在检测工具 APP 的帧回调中不停读取录屏画面,并和上次检测画面 hash 值进行比对。

  • 检测工具 APP 和目标 APP 进程隔离,为此目标 APP 发生卡顿并不影响检测工具 APP 的帧回调

  • 为保证每次录屏画面读取和 hash 值计算在 16.6ms 内完成,需根据高低端机型调整画面宽高压缩比。

为排除滑动操作对流畅度数值的干扰,我们使用脚本操作检测工具 APP 和目标 APP 的滑动。自动化脚本原理为使用 adb 命令操作手机

点击:adb shell input tap $x $y

滑动:adb shell input swipe $x1 $y1 $x2 $y2 $duration

2.4 检测工具演示

流畅度检测工具 APP 以悬浮框的方式显示,下面为目标检测 APP:

流畅度检测工具界面

2.5 小结和展望

在流畅度指标方面,我们定义了平均 FPS 和 1s 大卡顿次数作为指标,更好的反应了用户体验。

在流畅度检测工具方面,我们实现了无侵入检测工具,支持以下特性:

  • 无侵入

  • 支持检测第三方 app

  • 支持多平台:native,flutter,h5,小程序

  • 多维度数据:平均 FPS,平均 1s 大卡帧次数,帧分布直方图,帧分布均方差

  • 自动操作,避免人为操作差异

此外,流畅度检测工具还有一些不足之处

  • 列表中有视频卡片

  • 停止滑动时,若列表中有视频播放,由于画面一直在变化,检测工具无法判断是滑动停止;同时,由于视频 fps 值为 30 左右,会导致流畅度数据偏低

  • 如何避免:检测过程中,需保证列表滑动不停止

  • 低端机(y67)真实 fps 计算存在偏差

  • 为保证低端机上(如 vivo y67)上计算大图像 hash 值在 16ms 以内,录屏画面压缩较大(宽度压缩 100,高度压缩 10),为此在大量空白或者大色块的场景下,无法检测到画面的细微变化,fps 计算存在偏低。

  • 如何避免:避免低端机上检测大量空白或大色块的场景

3 原生 Android 长列表优化


Android 原生长列表优化已经非常成熟了,在工具方面有 traceview、blockcanary、DDMS、Android Profile 等。常见优化手段也很多:布局层级优化,过度渲染优化,频繁measure、layout优化,UI 线程耗时方法优化、冗余资源资源加载优化等,这里不再赘述。

除此之外闲鱼使用以下 2 点优化首页

3.1 异步构建视图缓存池

通过工具检测或耗时打印,发现列表初始滑动和 loadmore 时触发 item 视图构建耗时严重(RecyclerView.onCreateViewHolder)

查看首页显示和初始滑动流程,可以发现流程中其他 UI 操作过程和等待用户操作过程均有优化空间。

利用 AsyncLayoutInflater 原理异步构建视图缓存池,优化首页列表流程如下:

其中视图缓存池构建完成的时机在不同机型下不同,可能在列表首屏多卡片构建之前,或构建中,或在用户滑动操作之前完成,或一开始构建就抛出错误停止构建

注意:不能直接使用 AsyncLayoutInflater,AsyncLayoutInflater 在异步构建失败后有一个降级到 UI 线程构建的逻辑,为避免降级逻辑发生导致缓存池在 UI 线程构建,导致页面更加卡顿,需要移除这个降级逻辑:出现异步 inflater 失败,停止缓存池构建。

3.2 ViewDataUnbinder 快速抽离 UI 操作

在卡片数据绑定阶段(RecyclerView.onBindViewHolder),在低端机上耗时较为严重,原因是在卡片数据绑定方法中,而 UI 和非 UI 操作糅合在一起,由于 UI 逻辑必须在 UI 线程执行,最终导致全部逻辑只能在 UI 线程执行。

能想到定义视图数据层,将 UI 和非 UI 操作分离开,然而实际编码发现业务代码改动量大且容易出错,AB 测试逻辑难以实现。那有没有更好的方案,用最少量代码抽离 UI 操作呢?

核心思路:编译期根据视图类自动生成 ViewData 类,并替换视图类实例。ViewData 类和视图类拥有相同的关键方法签名,方法执行时记录视图操作,统一切换到 UI 线程执行视图操作。

具体使用代码样例如下

  1. 注解视图类

使用 ViewDataAnno 注解视图类,UIMethodAnno 注解 UI 操作方法。

  1. 生成 ViewData 类

  1. 业务代码修改
  • 修改视图变量为 ViewData 类型

  • 原视图数据绑定逻辑放置后台线程

3.3 优化结果

闲鱼首页,在恢复内容上屏速度(流畅度降低)后提升流畅度

4 Flutter 复杂长列表优化


flutter 一直以高性能被大家所认知,参考 Flutter 是如何做到性能直逼 native 的?,这也是闲鱼当初选择 flutter 的一个重要原因。而在闲鱼的实际 flutter 页面,如商品详情页和搜索结果页,长列表滑动流畅度体验却不尽人意。

4.1 工具使用和常见优化

做性能优化前,需要理解 flutter 的渲染原理,如 Widget、Element、RenderObject 三棵树结构、Widget 到屏幕显示过程等,可参考 超详解析Flutter渲染引擎, 复杂业务如何保证Flutter的高性能高流畅度?

针对性能问题,首推官方性能分析工具并结合使用 profile 模式查看性能问题,参考 Flutter Performance 分析工具简介

Profile 模式只能在真机上运行,不能在模拟器上运行:基本和 Release 模式一致,除了启用了服务扩展和 tracing,以及一些为了最低限度支持 tracing 运行的东西(比如可以连接 observatory 到进程)。命令 flutter run --profile 就是以这种模式运行的,通过 sky/tools/gn --android --runtime-mode=profile 或者 sky/tools/gn --ios --runtime-mode=profile 来 build。因为模拟器不能代表真实场景,所以不能在模拟器上运行

引自:Flutter性能调优、复杂业务保证Flutter的高性能高流畅

4.1.1 检查 widget rebuild 情况

Android Studio 上 View → Tool Windows → Flutter Performance 打开检测 Widget rebuild 情况,可以发现 FDButtonBar 被频繁重建,然而查看视图内容并没有发生变化。查看代码定位到 reducer.dart 中会根据滑动事件更新 state 中的 scrollPercent,进而产生重建。而在详情页中,scrollPercent 在 Widget 构建中并未参与使用。

闲鱼页面中使用了 fish-redux,在 reducer.dart 的方法中返回不同的 state 对象则表示需要重建 widget

// reducer.dart

// 滑动事件监听

static BottomBarState onScroll(BottomBarState state, Action action) {

return state.clone()…scrollPercent = scrollPercent;

}

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

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

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

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

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

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

总结

其实要轻松掌握很简单,要点就两个:

  1. 找到一套好的视频资料,紧跟大牛梳理好的知识框架进行学习。
  2. 多练。 (视频优势是互动感强,容易集中注意力)

你不需要是天才,也不需要具备强悍的天赋,只要做到这两点,短期内成功的概率是非常高的。

对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。

以上就是总结的关于在面试的一些总结,希望对大家能有些帮助,除了这些面试中需要注意的问题,当然最重要的就是刷题了,这里放上我之前整理的一份超全的面试专题PDF

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

【Android核心高级技术PDF文档,BAT大厂面试真题解析】

这里只是整理出来的部分面试题,后续会持续更新,希望通过这些高级面试题能够降低面试Android岗位的门槛,让更多的Android工程师理解Android系统,掌握Android系统。喜欢的话麻烦点击一个喜欢在关注一下~

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

的话麻烦点击一个喜欢在关注一下~

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值