Skip to content
阅读进度

用了异步 Inflate,生命周期与界面怎么协调? ​

返回 工程项目复盘 目录

标准回答 ​

异步 Inflate 的作用,是把允许在后台创建的布局工作移出主线程,减轻启动关键路径的负担。我在冷启动优化中使用过它,但它不会让 Activity 生命周期等待布局完成。

因此设计时要把“页面处于哪个生命周期”和“布局是否准备好”分开看。布局还没创建完成,页面可能已经 onResume;回调回来时,用户也可能已经退出。结果不能不加判断地附加到界面,必须确认页面和当前加载任务仍然有效,并在正确线程执行附加与 UI 绑定。

它也不是任何布局都可以直接后台创建。自定义控件构造过程如果依赖主线程能力,异步创建可能不适用或发生回退,收益就需要通过实际 Trace 检查。与其把整棵复杂布局无差别异步化,我更关心哪些部分阻塞首屏、哪些部分可以按需加载。

展示上还要保证关键内容的整体性。多个区域完成时间不同,如果每完成一块就立刻显示,可能出现页面一块块冒出来的割裂感。因此性能优化需要同时考虑布局就绪、交互就绪和视觉呈现,不能只追求生命周期回调更早结束。

关键机制 ​

  • 主线程更新和附加 View;不是任意自定义控件都能后台构造,回退主线程会影响实际收益。
  • 关键首屏先完整呈现,复杂或非必要区域按需准备;不能只追求快亮屏而长期不可交互。
  • 处理回调晚到、重复进入、旋转与销毁;只做判空不能替代当前会话和页面有效性判断。

通俗例子 ​

如果用户快速进入再退出,布局创建结束时页面可能已销毁。候选处理是取消可取消工作或忽略过期结果,避免把旧 View 附加到新页面。

追问与回答 ​

为什么页面看起来一块块加载? ​

因为异步让不同区域在不同时间准备好,如果回调一到就立即显示,用户会看到内容分批出现。解决时先区分关键首屏和非关键区域:关键内容需要一致的呈现策略,非关键区域可以有明确的占位或延后展示。不能为了隐藏分批加载又让主线程阻塞等待全部完成,而是要控制依赖和展示时机。

findViewById、setSelected 能一起放后台吗? ​

不能把异步创建理解成任意 View 操作都可以后台执行。尤其是已经附加到界面的 View,状态更新要遵守主线程规则。异步结果回调后,应在合适的 UI 阶段完成绑定和状态应用;后台更适合准备数据。是否某个查找操作本身可行,也不能代替对整条调用链线程安全的判断。

易混淆点 ​

“异步导致 onResume 乱序”不准确;系统生命周期照常推进,变化的是内容准备时间。

参考资料 ​

内容来源 ​

用完整回答理解机制,用真实证据解释项目。