从ViewPager迁移到ViewPager2后如何用FragmentStateAdapter替换Fragment
ViewPager2搭配FragmentStateAdapter实现Fragment替换的解决方案
核心原理
FragmentStateAdapter没有getItemPosition方法,它通过getItemId(int position)返回的唯一ID判断对应位置的Fragment是否需要重建,默认实现直接返回position值,因此修改对应位置的Fragment实例后,适配器无法感知变化,不会触发重建。
修改方案
1. 调整适配器代码
新增唯一标识变量,复写getItemId和containsItem方法,修改替换逻辑:
public class BottomNavigationIcon extends FragmentStateAdapter implements FragChangeListner { FragmentManager fm; Fragment tmp; // 新增:记录位置3的Fragment唯一标识,每次切换自增 private long position3FragmentId = 0; public BottomNavigationIcon(@NonNull FragmentManager fragment, Lifecycle lc) { super(fragment,lc); this.fm=fragment; } @NonNull @Override public Fragment createFragment(int position) { if (position == 1) return SessionFragment.getInstance(); if (position == 2) return OthersFragment.newInstance(); if (position == 3) { if (tmp == null) tmp = SettingsFragment.newInstance(); return tmp; } return ProcessFragment.newInstance(); } @Override public int getItemCount() { return 4; } // 复写返回每个位置的唯一标识 @Override public long getItemId(int position) { if (position == 3) { return position3FragmentId; } // 其他位置用默认实现即可 return super.getItemId(position); } // 复写判断指定ID对应的项是否仍存在 @Override public boolean containsItem(long itemId) { // 只要当前ID和最新的position3FragmentId一致就认为存在 return itemId == position3FragmentId || super.containsItem(itemId); } @Override public void replaceFrag() { // 无需手动移除旧Fragment,FragmentStateAdapter会自动处理生命周期 tmp = AboutFragment.newInstance(); // 标识自增,通知适配器位置3的项已变更 position3FragmentId++; notifyDataSetChanged(); } }
2. 修正接口语法错误
你提供的接口定义存在语法问题,修改如下:
public interface FragChangeListner { void replaceFrag(); }
注意事项
- 不要手动通过
FragmentManager移除FragmentStateAdapter管理的Fragment,适配器会自动处理销毁和重建逻辑,手动操作可能引发内存泄漏或崩溃 - 若需要多个位置支持动态替换,可以用
SparseArray<Long>存储每个位置的标识变量,按需修改对应位置的ID即可
内容的提问来源于stack exchange,提问作者Naveen Kumar
相关产品推荐
相关产品推荐

