尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

用DiffUtil高效管理ViewPager2中的Fragment:Android-Extensions FragmentListAdapter实战

用DiffUtil高效管理ViewPager2中的Fragment:Android-Extensions FragmentListAdapter实战 用DiffUtil高效管理ViewPager2中的FragmentAndroid-Extensions FragmentListAdapter实战【免费下载链接】Android-ExtensionsAn Android library with modules to quickly bootstrap an Android application.项目地址: https://gitcode.com/gh_mirrors/an/Android-ExtensionsAndroid-Extensions是一个用于快速搭建 Android 应用的扩展库集合其中的FragmentListAdapter组件将DiffUtil差量刷新机制引入ViewPager2让你用一行submitList()就能高效管理滑动页面中的 Fragment彻底告别整页重建的性能陷阱。为什么 ViewPager2 中刷新全部Fragment 会卡顿用官方的FragmentStateAdapter管理 ViewPager2 时最常见的做法是数据一变就调用notifyDataSetChanged()。问题在于这会把 ViewPager2 里的所有页面全部销毁重建后果是 当前正在浏览的页面闪动动画和滚动状态丢失 Fragment 频繁创建销毁白白消耗 CPU 页面数量一多滑动开始掉帧根因在于位置被当成了身份。RecyclerView 早已用 DiffUtil 解决这个问题而 ViewPager2 底层恰恰就是 RecyclerView——它同样值得一次精准的差量更新。FragmentListAdapter基于 DiffUtil 的 ViewPager2 适配器FragmentListAdapter位于库的viewpager2模块源码文件为viewpager2/src/main/java/com/tunjid/viewpager2/FragmentListAdapter.kt模块说明见viewpager2/README.md。它的核心设计一句话就能讲清内部封装了AsyncListDiffer提交新数据后先在后台线程对比新旧列表只重建真正发生变化的页面未变的 Fragment 原地保留。⚡它有三个关键设计点FragmentTab接口每个页签都是一个有身份的对象而不再是一个孤立的 position 数字稳定的itemId由FragmentTab的类全名 hashCode()共同哈希生成保证页面身份在数据重排后依然稳定submitList(newTabs)一行代码提交新数据差量计算与 UI 更新自动完成实现 FragmentTab两个方法让页面拥有身份FragmentTab接口只有两个方法实现成本极低方法作用createFragment()告诉适配器该页要创建哪个 Fragmenttitle(res)提供页签标题配合 TabLayout 显示页签文字⚠️ 官方强烈建议用data class来实现FragmentTab至少要保证equals和hashCode稳定——DiffUtil 的整个比对逻辑就建立在这之上。实战案例3 行代码搭建 Doggo 滑动页 示例 App 中有一个完整的实战案例DoggoPagerFragment源码app/src/main/java/com/tunjid/androidx/tablists/doggo/DoggoPagerFragment.kt用该适配器渲染了 9 页狗狗图片配合自定义指示器实现点击小圆点跳转页面整体代码如下所示核心仅 3 行// 页签定义data class 保证身份稳定 private data class DoggoTab(val doggo: Doggo) : FragmentTab { override fun title(res: Resources) override fun createFragment() DoggoFragment.newInstance(doggo) } // 一行创建适配器 一行挂载到 ViewPager2 val adapter fragmentListAdapterOf(Doggos.map(::DoggoTab)) binding.viewPager.adapter adapter之后数据再怎么变化只需要adapter.submitList(newTabs)DiffUtil 会自动比对新旧列表只有真正变化的页面才会重建其余 Fragment 保持不动。另外fragmentListAdapterOf扩展函数在Fragment和FragmentActivity上都可用前者自动使用childFragmentManager后者使用supportFragmentManager生命周期也都已按最佳实践接好无需手动处理。进阶用 Diffable 接口精准控制差量粒度 FragmentListAdapter的比对逻辑由recyclerview模块的DiffAdapterCallback驱动源码recyclerview/src/main/java/com/tunjid/androidx/recyclerview/diff/DiffAdapterCallback.kt它可以感知Diffable接口定义于recyclerview/src/main/java/com/tunjid/androidx/recyclerview/diff/Differentiable.kt成员作用diffId判断是不是同一个条目——数据重排时只做移动不重建areContentsTheSame判断内容是否变化——避免无谓重建getChangePayload提供变化负载支持局部更新示例中的Doggo数据类源码app/src/main/java/com/tunjid/androidx/tablists/doggo/Doggo.kt就实现了Diffable以name拼接哈希作为diffId。这样一来即使把某只狗狗在列表中挪个位置ViewPager2 也只是移动了页面而不会销毁重建。接入指南3 步用上 FragmentListAdapter ✅第 1 步获取依赖。模块制品发布在 Maven Central在build.gradle中添加implementation com.tunjid.androidx:viewpager2:version也可以克隆源码仓库自行构建git clone https://gitcode.com/gh_mirrors/an/Android-Extensions第 2 步定义页签类型。为你的页面数据实现FragmentTab用 data class 承载业务数据即可。第 3 步挂载并刷新。在Fragment或FragmentActivity中调用fragmentListAdapterOf(initialTabs)创建适配器赋值给viewPager.adapter数据更新时统一走submitList(newTabs)。总结 FragmentListAdapterFragmentStateAdapterAsyncListDiffer DiffUtil为 ViewPager2 提供差量刷新能力FragmentTab用 data class 实现让每个页面拥有稳定身份是差量比对生效的前提数据更新只需submitList()一行从此告别notifyDataSetChanged的整页重建需要更精细的差量控制时让数据模型实现recyclerview模块的Diffable接口如果你的项目里 ViewPager2 页面越来越多、数据越来越动态这个组件值得放进你的工具箱。【免费下载链接】Android-ExtensionsAn Android library with modules to quickly bootstrap an Android application.项目地址: https://gitcode.com/gh_mirrors/an/Android-Extensions创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表