使用Navigation Jetpack导航时带RecyclerView的Fragment进入动画卡顿或被跳过
动画异常的定位流程
- 先做对照场景测试缩小问题范围
- 给API请求手动加不同时长的模拟延迟,分别测试50ms、200ms、500ms延迟下的转场表现:如果短延迟下出现动画卡顿/跳过、长延迟下动画完全正常,可直接锁定核心矛盾是数据加载任务和转场动画的渲染窗口重叠,抢占主线程资源
- 抓主线程耗时证据,确认跳过/卡顿的具体触发点
- 用Android Studio CPU Profiler在转场全流程录制主线程Trace,标记转场动画的启动时间点,核对两个关键耗时:
- 转场动画运行的全周期内,主线程是否存在单帧超过16ms的阻塞任务:如果单次阻塞时长超过动画总时长的1/3,系统会直接判定动画掉帧严重,自动跳过后续动画帧。注意Navigation转场动画没有独立的错误日志,如果主线程在动画启动后100ms内未响应Choreographer的帧同步信号,系统会直接终止动画流程,不会抛出任何异常
- 检查RecyclerView的首次layout、首屏item绘制的时间点是否落在动画运行区间:如果这部分绘制任务刚好处在动画启动后的前300ms,会直接占用动画渲染的CPU时间片导致卡顿
- 排查Navigation转场的配置逻辑:如果当前导航配置了共享元素转场,且共享元素绑定的是RecyclerView本身,当动画启动时RecyclerView还未完成首次layout,Navigation框架会无日志直接跳过转场动画
- 用Android Studio CPU Profiler在转场全流程录制主线程Trace,标记转场动画的启动时间点,核对两个关键耗时:
对应问题的落地方案
- 错开任务时序,避免和动画渲染抢资源
- 把原本在
onViewCreated中发起的API请求、RecyclerView首次数据绑定操作,延后到转场动画完全结束后再触发:可通过监听目标Fragment的生命周期事件,在ON_RESUME回调后延迟300ms(对应Jetpack Navigation默认转场动画的标准时长)再发起网络请求,从根源上避免任务重叠 - 转场动画运行期间,仅给RecyclerView绑定简单的占位布局,不要触发真实数据的全量绘制
- 把原本在
- 修正转场配置,避免无日志的动画跳过
- 如果没有使用共享元素转场,移除导航配置中绑定RecyclerView的共享元素关联逻辑,防止因View未完成layout触发动画跳过
- 提前校验系统动画开关状态:在转场前读取系统设置中的
windowAnimationScale参数,如果参数为0,直接跳过动画相关的逻辑处理,避免无意义的资源消耗
- 降低RecyclerView的主线程开销,减小动画期间的性能压力
- 把API返回的JSON解析、数据实体映射逻辑全部移到子线程执行,不要在主线程做复杂的数据转换
- 列表首次更新不要使用全量
notifyDataSetChanged(),可在动画结束后通过DiffUtil做差分更新,减少全量绘制带来的主线程耗时 - 转场期间临时关闭RecyclerView的预取功能,给LayoutManager设置
setItemPrefetchEnabled(false),避免RecyclerView提前预加载屏幕外item占用渲染资源
内容的提问来源于stack exchange,提问作者kunal jaiswal
相关产品推荐
相关产品推荐

