如何从ViewPager获取当前Fragment?为何Fragment列表仅3个?
getFragments()只返回3个Fragment? 这个问题我之前也碰到过,核心原因是ViewPager的预加载机制在搞鬼!ViewPager默认的offscreenPageLimit属性值是1,意思是它会提前加载当前选中页面左右各1个页面对应的Fragment,保证滑动切换时更流畅。所以当你处于任意一个页面时,最多只会有3个Fragment被实例化并加入FragmentManager的管理中,剩下的那个还没被创建,自然不会出现在getFragments()的返回列表里。
我给你推荐几个实用的解决方法,按易用性和稳定性排序:
1. 自己维护Fragment引用列表
这是最直接也最不容易踩坑的方式,在PagerAdapter里提前把每个Fragment的引用存进列表,之后直接通过position就能拿到对应Fragment。
示例代码:
首先在你的Activity或者Adapter里定义一个Fragment列表:
private List<Fragment> mFragmentList = new ArrayList<>();
然后在PagerAdapter初始化时,把所有Fragment添加进去(以FragmentPagerAdapter为例):
public class MyPagerAdapter extends FragmentPagerAdapter { public MyPagerAdapter(FragmentManager fm) { super(fm); // 提前初始化所有Fragment并存入列表 mFragmentList.add(new Fragment1()); mFragmentList.add(new Fragment2()); mFragmentList.add(new Fragment3()); mFragmentList.add(new Fragment4()); } @Override public Fragment getItem(int position) { return mFragmentList.get(position); } @Override public int getCount() { return mFragmentList.size(); } }
之后在onPageSelected里直接获取:
@Override public void onPageSelected(int position) { Fragment currFragment = mFragmentList.get(position); // 这里就可以放心操作当前Fragment了 }
如果你的Fragment是动态创建的,也可以在instantiateItem方法里更新列表(避免getItem被缓存导致的引用失效问题):
@Override public Object instantiateItem(ViewGroup container, int position) { Fragment fragment = (Fragment) super.instantiateItem(container, position); mFragmentList.set(position, fragment); return fragment; }
2. 通过Fragment的Tag查找
ViewPager在创建Fragment时,会给每个Fragment分配一个固定格式的Tag:"android:switcher:" + viewPager.getId() + ":" + position。你可以根据这个规则构造Tag,然后通过FragmentManager直接查找。
示例代码:
@Override public void onPageSelected(int position) { // 先拿到你的ViewPager实例 ViewPager viewPager = findViewById(R.id.your_viewpager_id); String fragmentTag = "android:switcher:" + viewPager.getId() + ":" + position; Fragment currFragment = getSupportFragmentManager().findFragmentByTag(fragmentTag); if (currFragment != null) { // 操作当前Fragment } }
这个方法不需要额外维护列表,但要确保ViewPager的id正确,不过onPageSelected触发时,当前页的Fragment肯定已经被实例化了,所以不用担心空指针问题。
3. 修改ViewPager的预加载数量(不推荐)
虽然可以把offscreenPageLimit设为3(因为总共有4个Fragment),这样所有Fragment都会提前加载,getFragments()就能拿到4个,但这种方式会占用更多内存,尤其是Fragment里包含大量图片或资源时,会明显影响App性能,所以非常不建议这么做。
示例代码(仅作参考):
viewPager.setOffscreenPageLimit(3);
内容的提问来源于stack exchange,提问作者bircastri

