ViewPage中Fragment替换失败的解决方法

xiaoxiao2021-02-28  118

相信在android开发中,使用ViewPage是必须的,而和ViewPage配合使用的那就属Fragment最为常见了,还有就是ImageView。 今天所说的是Fragment在ViewPage中的使用,通常我们所使用的适配器是FragmentPagerAdapter。一般情况下,我们在ViewPage中添加的碎片(Fragment)是固定的,不会发生变更的,那么在FragmentPagerAdapter适配器中重写的几个方法就是固定的,不需要重写其他的方法,这里我就不再赘述了。 可是如果ViewPage中的碎片在某种情况下出现替换,该如何处理呐? 通常的思路就是: 使用 FragmentPagerAdapter 将所有的碎片添加到ViewPage中,如果在某个条件的触发下,更改Fragment的数据源,然后再通过notifyDataSetChanged()的方法,通知适配器更新数据,可是如果这样运行的话,发现其中该被替换掉的碎片没有被替换掉,还是会出现原先的碎片,不管你如何清理ViewPage中的控件、如何更改数据源,碎片始终还是不会被替换。 那我们就会想,代码没问题呀!逻辑没错呀!为什么就是不被替换呐???? 我认为这个主要是缓存的问题,我们第一次添加到ViewPage中的碎片被放到了缓存中了,等我们需要替换其中某个碎片时,只是更改了数据源,而在缓存中的还是之前的碎片,所以不管你怎么切换都不会把碎片替换掉。 其实解决的方法有三种:

一、继续使用FragmentPagerAdapter ,重写 instantiateItem(ViewGroup container, int position) 方法。 贴上适配器中的代码如下:

public class MyAdapter extends FragmentPagerAdapter { protected List<Fragment> fragmentsList; //数据源 private boolean[] flags; //标记碎片的 private FragmentManager fm; public MyAdapter(FragmentManager fm, List<Fragment> fragments) { super(fm); this.fm = fm; this.fragmentsList = fragments; flags = new boolean[fragmentsList.size()]; } //提供一个公共方法,供其他类调用,刷新适配器 public void refresh(int... indexs) { for (int i = 0; i < indexs.length; i++) { flags[indexs[i]] = true; } notifyDataSetChanged(); } /** * POSITION_NONE;//返回这个表示该对象已改变,需要刷新 * POSITION_UNCHANGED;//反之不刷新 */ @Override public int getItemPosition(Object object) { // TODO Auto-generated method stub return PagerAdapter.POSITION_NONE; } //这个方法是重点,只有重写了这个方法才会实现碎片的替换。 @Override public Object instantiateItem(ViewGroup container, int position) { Fragment fragment = (Fragment) super.instantiateItem(container, position); // 得到Tag String fragmentTag = fragment.getTag(); if (flags[position % flags.length] && fragment != fragmentsList.get(position % fragmentsList.size())) { // 如果这个Fragment需要更新 FragmentTransaction ft = fm.beginTransaction(); // 移除旧的Fragment ft.remove(fragment); // 换成新的Frgment fragment = fragmentsList.get(position % fragmentsList.size()); // 用之前的Tab添加新的Frgament ft.add(container.getId(), fragment, fragmentTag); ft.attach(fragment); ft.commitAllowingStateLoss(); // 复位更新标志 flags[position % flags.length] = false; } return fragment; } @Override public int getCount() { return fragmentsList.size(); } @Override public Fragment getItem(int arg0) { return fragmentsList.get(arg0); } }

二、使用FragmentStatePagerAdapter适配器,也许重写instantiateItem(ViewGroup container, int position) 。 代码如下:

public class ViewPageAdapter extends FragmentStatePagerAdapter { private List<Fragment> mDataList; public ViewPageAdapter(FragmentManager fm, List<Fragment> list) { super(fm); mDataList = list; } @Override public Fragment getItem(int position) { return mDataList.get(position); } @Override public int getItemPosition(Object object) { return PagerAdapter.POSITION_NONE; } @Override public int getCount() { return mDataList.size(); } @Override public Object instantiateItem(ViewGroup container, int position) { final Object fragment = super.instantiateItem(container, position); try { final Field saveFragmentStateField = Fragment.class.getDeclaredField("mSavedFragmentState"); saveFragmentStateField.setAccessible(true); final Bundle savedFragmentState = (Bundle) saveFragmentStateField.get(fragment); if (savedFragmentState != null) { savedFragmentState.setClassLoader(Fragment.class.getClassLoader()); } } catch (Exception e) { e.printStackTrace(); } return fragment; } }

三、使用Fragment的管理器FragmentManager来对Fragment进行替换。 具体方法点击此链接

以上三种方法是我对Fragment的替换所采取的方法,如若有更好的方法或有不足之处,望指出!谢谢!

转载请注明原文地址: https://www.6miu.com/read-66519.html

最新回复(0)