恢复 RecyclerView 的滚动位置

您可能在开发过程当中遇到过这种状况,在 Activity/Fragment 被从新建立后,RecyclerView 丢失了它以前保有的滚动位置信息。一般这种状况发生的缘由是因为异步加载 Adapter 数据,且数据在 RecyclerView 须要进行布局的时候还没有加载完成,致使 RecyclerView 没法恢复到以前的滚动位置。android

从  1.2.0-alpha02 版本开始,Jetpack RecyclerView 提供了一个新的 API,可让 Adapter  在数据加载完成以前阻塞布局行为 ,从而避免丢失滚动位置信息。接下来咱们会介绍如何使用这个新的 API,以及它的工做原理。缓存

恢复至原有滚动位置

有好几种方法能够用来恢复 RecyclerView 至正确的滚动位置,您可能已经在实际项目中用到了这些方法。其中最好的一种方法是将数据提早缓存在内存、ViewModel 或 Repository 中,而后确保在第一次布局传入以前,将缓存的数据设置到 Adapter 中去。若是根据您的项目实际状况没法采用这种方法,那也可使用其余的方法,只是要么比较复杂 (好比避免在 RecyclerView 中设置 Adapter,但这样又有可能致使像 header 等 item 的显示问题),要么会致使 LayoutManager.onRestoreInstanceState) API 被滥用。异步

recyclerview:1.2.0-alpha02 版本中提供的解决方案是引入一个新的 Adapter 方法,来容许您设置它的状态恢复策略 (经过枚举类型 StateRestorationPolicy)。它有三个选项:布局

  • ALLOW — 默认状态,会在下一次布局完成时当即恢复 RecyclerView 状态;
  • PREVENT_WHEN_EMPTY — 仅当 adapter 不为空 (即 adapter.getItemCount() > 0) 的时候,才恢复 RecyclerView 的状态。若是您是异步加载数据,RecyclerView 会等待数据加载完毕以后,才对状态进行恢复。若是在 Adapter 中有一些默认的 item,好比 header 或是 load progress indicator,那您应该使用 PREVENT 选项,除非是经过 ConcatAdapter 添加默认的 item,了解更多详细信息,请查阅《使用 ConcatAdapter 顺序链接其余 Adapter》。ConcatAdapter 会等待全部的 adapter 所有准备就绪后,才进行状态的恢复;
  • PREVENT — 全部的状态恢复都会等到您设置了 ALLOW 或者 PREVENT_WHEN_EMPTY 选项,才会获得执行。

经过以下示例代码可设置 adapter 的状态恢复策略:google

adapter.stateRestorationPolicy = PREVENT_WHEN_EMPTY

经过这篇短小精悍的文章您能够了解到关于 RecyclerView 的延迟状态恢复 (lazy state restoration) 功能。赶快开始使用吧!rest

相关文章
相关标签/搜索