ViewPager中使用FragmentPagerAdapter.notifyDataSetChanged无法更新当前Fragment解决方案

最近,在使用ViewPager和FragmentPagerAdapter时遇到如下问题(为了说明问题先上图):
图一

ViewPager中使用FragmentPagerAdapter.notifyDataSetChanged无法更新当前Fragment解决方案_第1张图片

图二

ViewPager中使用FragmentPagerAdapter.notifyDataSetChanged无法更新当前Fragment解决方案_第2张图片

功能描述:该页面为ViewPager的实现,且一共有两个Fragment:Fragment01与Fragment03;左右滑动可实现Fragment01与Fragment03的切换。现有需求:
点击button01与button02可进行Fragment01与Fragment02的替换,即Fragment03不会发生变化,只在原Fragment01上进行UI的替换。
其效果为图一与图三的切换。
图三

ViewPager中使用FragmentPagerAdapter.notifyDataSetChanged无法更新当前Fragment解决方案_第3张图片

实现代码(注意里面的注释):
1.MainActivity 用到了xutils3中的注解
public class MainActivity extends AppCompatActivity {

    private int buttonClickTime = 0;
    @ViewInject(R.id.button)
    private Button button;
    @ViewInject(R.id.turn01_bn)
    private Button turn01_bn;
    @ViewInject(R.id.turn02_bn)
    private Button turn02_bn;
    @ViewInject(R.id.viewPager)
    private ViewPager viewPager;
    private MyViewPagerAdapter adapter;


    @Event(value = {R.id.button, R.id.turn01_bn, R.id.turn02_bn}, type = View.OnClickListener.class)
    private void buttonOnClickListener(View v) {
        switch (v.getId()) {
            case R.id.turn01_bn:
                adapter.button01IsClicked = true;
                // 用于记录button01被点击了
                adapter.notifyDataSetChanged();
                //刷新ViewPager
                break;
            case R.id.turn02_bn:
                adapter.button02IsClicked = true;
                // 用于记录button02被点击了
                adapter.notifyDataSetChanged();
                //刷新ViewPager
                break;
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        x.view().inject(this);
        initView();
    }

    private void initView() {
        adapter = new MyViewPagerAdapter(getSupportFragmentManager());
        viewPager.setAdapter(adapter);
        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
                                              @Override
                                              public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

                                              }

                                              @Override
                                              public void onPageSelected(int position) {
                                              // Fragment切换时隐藏button
                                                    if(position == 1){
                                                        turn01_bn.setVisibility(View.GONE);
                                                        turn02_bn.setVisibility(View.GONE);
                                                    }else{
                                                        turn01_bn.setVisibility(View.VISIBLE);
                                                        turn02_bn.setVisibility(View.VISIBLE);
                                                    }
                                              }

                                              @Override
                                              public void onPageScrollStateChanged(int state) {

                                              }
                                          }
        );
    }

}
运行后你会发现adapter.notifyDataSetChanged()并不能进行当前页面的更新(这里的更新是根据button01IsClicked 和button02IsClicked返回不同的Fragment)。这是由FragmentPagerAdapter的缓存机制造成的;具体原因如下:调用adapter.notifyDataSetChanged()方法后adapter会调用getItemPosition(),getItemPosition()会根据当前Fragment判断是否在缓存中,如果是直接从缓存中获取Fragment,否则会调用instantiateItem(ViewGroup container, int position)这个方法。所以,为了实现同一位置的Fragment,必须复写这两个方法,具体代码如下:
2.MyViewPagerAdapter 
public class MyViewPagerAdapter extends FragmentPagerAdapter {

    private android.support.v4.app.FragmentManager fm;
    public List<Fragment> list;
    private Test02Fragment fr02;

    public boolean button01IsClicked = false;// 用于区别点击的是哪个按钮
    public boolean button02IsClicked = false;// 用于区别点击的是哪个按钮

    public MyViewPagerAdapter(android.support.v4.app.FragmentManager fm) {
        super(fm);
        this.fm = fm;
        list = new ArrayList<Fragment>();
        list.add(new Test01Fragment());
        list.add(new Test03Fragment());
        fr02 = new Test02Fragment();
    }

    @Override
    public int getCount() {
        return list.size();
    }

    @Override
    public Fragment getItem(int position) {
        return list.get(position);
    }

    @Override
    public int getItemPosition(Object object) {
    // 这里根据Fragment的类型进行选择是否重新生成,这样能尽可能地提高FragmentPagerAdapter 的性能
        if (object.getClass().getName().contains("Test01Fragment") || object.getClass().getName().contains("Test02Fragment")) {
            return POSITION_NONE;// 返回这个值,表示需要重新生成Fragment
        } else {
            return super.getItemPosition(object);
        }
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        //得到缓存的fragment
        Fragment fragment = (Fragment) super.instantiateItem(container,
                position);
        // 判断当前Fragment是属于哪一个Fragment
        boolean isTwo = fragment.getClass().getName().contains("Test02Fragment");
        //得到tag,这点很重要
        String fragmentTag = fragment.getTag();

        if (position == 0) {
            //如果这个fragment需要更新
            android.support.v4.app.FragmentTransaction ft = fm.beginTransaction();
            if (button01IsClicked && isTwo) {
                //移除旧的fragment
                ft.remove(fragment);
                //换成新的fragment
                fragment = list.get(0);
                //添加新fragment时必须用前面获得的tag,这点很重要
                ft.add(container.getId(), fragment, fragmentTag);
                ft.attach(fragment);
                ft.commit();
            }
            if (button02IsClicked && !isTwo) {
                //移除旧的fragment
                ft.remove(fragment);
                //换成新的fragment
                fragment = fr02;
                //添加新fragment时必须用前面获得的tag,这点很重要
                ft.add(container.getId(), fragment, fragmentTag);
                ft.attach(fragment);
                ft.commit();
            }

        }
        // 重置按钮的点击状态
        button01IsClicked = false;
        button02IsClicked = false;
        return fragment;
    }
}
到这里就可以实现点击按钮替换Fragment了
demo地址:http://download.csdn.net/detail/niuzhucedenglu/9461414
参考资料:
http://my.oschina.net/8048/blog/531070?fromerr=x6bUiu15
http://blog.csdn.net/zmldlut/article/details/17689011
http://blog.sina.com.cn/s/blog_783ede03010173b4.html
http://blog.csdn.net/dreamzml/article/details/9951577
http://www.blog4app.com/?p=62
http://www.tuicool.com/articles/eua2mm
http://blog.csdn.net/dreamzml/article/details/9951577

你可能感兴趣的:(viewpager,更新Fragment)