以下从多个维度对两者进行对比,包括核心代码、内存管理、适用场景等。
1. 所属组件及基类
-
FragmentPagerAdapter
- 用于
ViewPager(旧版组件)。 - 继承自
PagerAdapter。 - 适用于页面数量较少且相对静态的场景。
- 用于
-
FragmentStateAdapter
- 用于
ViewPager2(基于RecyclerView实现)。 - 继承自
RecyclerView.Adapter<FragmentViewHolder>。 - 更灵活,支持动态数据、垂直滑动、RTL 布局等。
- 用于
2. 内存管理策略
-
FragmentPagerAdapter
- 不销毁 Fragment:仅调用
detach()分离视图,Fragment 实例保留在内存中。 - 页面切换速度快,但内存占用高。
- 适合页面固定且数量少的情况(如 Tab 导航)。
- 不销毁 Fragment:仅调用
-
FragmentStateAdapter
- 销毁不可见 Fragment:通过
remove()和saveState()销毁实例,但保存状态(类似FragmentStatePagerAdapter)。 - 内存占用低,适合动态或大量页面(如轮播图、长列表)。
- 默认保留当前页及相邻页,其余销毁。
- 销毁不可见 Fragment:通过
3. 核心代码对比
FragmentPagerAdapter 实现
public class MyPagerAdapter extends FragmentPagerAdapter {
private static final int NUM_PAGES = 3;
public MyPagerAdapter(FragmentManager fm) {
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
}
@Override
public Fragment getItem(int position) {
return MyFragment.newInstance(position); // 创建新 Fragment
}
@Override
public int getCount() {
return NUM_PAGES;
}
// 可选:数据更新时标记位置无效
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
FragmentStateAdapter 实现
public class MyStateAdapter extends FragmentStateAdapter {
private static final int NUM_PAGES = 3;
public MyStateAdapter(FragmentActivity fa) {
super(fa);
}
@Override
public Fragment createFragment(int position) {
return MyFragment.newInstance(position); // 创建新 Fragment
}
@Override
public int getItemCount() {
return NUM_PAGES;
}
// 数据更新时直接调用 notify 方法
public void updateData() {
notifyDataSetChanged();
}
}
4. 数据更新方式
-
FragmentPagerAdapter
- 需重写
getItemPosition()返回POSITION_NONE,并调用notifyDataSetChanged()。 - 强制 ViewPager 重新加载所有页面,可能引发性能问题。
- 需重写
-
FragmentStateAdapter
- 直接调用
notifyItemChanged()或notifyDataSetChanged()(继承自RecyclerView.Adapter)。 - 支持增量更新,性能更优。
- 直接调用
5. 生命周期差异
-
FragmentPagerAdapter
- Fragment 实例始终存在,
onDestroyView()被调用但onDestroy()和onDetach()不会触发。 - 适合需要保持 Fragment 活跃状态的场景。
- Fragment 实例始终存在,
-
FragmentStateAdapter
- 不可见 Fragment 会被销毁,触发完整的
onDestroy()生命周期。 - 通过
SavedState恢复状态,适合内存敏感场景。
- 不可见 Fragment 会被销毁,触发完整的
6. 构造函数差异
-
FragmentPagerAdapter
- 需传入
FragmentManager和BEHAVIOR参数(如BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT)。
- 需传入
-
FragmentStateAdapter
- 需传入
FragmentActivity或Fragment(内部自动获取FragmentManager)。
- 需传入
7. 适用场景总结
| 场景 | FragmentPagerAdapter | FragmentStateAdapter |
|---|---|---|
| 页面数量少且固定 | ✔️ 适合 | ❌ 过度设计 |
| 页面数量多或动态变化 | ❌ 内存溢出风险 | ✔️ 适合 |
| 需要保存 Fragment 状态 | ❌ 需手动处理 | ✔️ 自动保存 |
| 垂直滑动/RTL 支持 | ❌ 不支持 | ✔️ 支持(ViewPager2) |
8. 关键结论
- 迁移建议:优先使用
ViewPager2+FragmentStateAdapter,因其功能更强大且内存友好。 - 性能取舍:少量页面用
FragmentPagerAdapter(快速响应),大量页面用FragmentStateAdapter(低内存占用)。 - 数据更新:
FragmentStateAdapter的增量更新更高效。