RossWeatherMap天气地图项目中踩的雷(一):Viewpager动态删除Fragment

  • 开发环境:Myeclipse
  • JDK版本:1.7
  • Android版本:21

最近在做一个基于百度地图的天气APP,用的Fragment+ViewPager+DrawerLayout结构。具体就是使用两个带有BaiduMapView的Fragment显示全国天气,然后自定义的Fragment显示具体选中的城市的天气信息。现在已经可以显示具体城市的天气信息了,在研究如何把全国天气加在百度地图上。
来说说踩到的第一个雷吧。
在DrawerLAyout里选择是否显示地图

点击tooglebutton后调用RemoveMapFragment删除MapFragment,再notifyDataSetChanged。

        mDrawerToggleButton
                .setOnCheckedChangeListener(new OnCheckedChangeListener() {

                    @Override
                    public void onCheckedChanged(CompoundButton buttonView,
                            boolean isChecked) {
                        if (!isChecked) {
                            RemoveMapFragment();
                            mMyFragmentPagerAdapter.notifyDataSetChanged();

                        } else {
                            InitMapFragment();
                            mMyFragmentPagerAdapter.notifyDataSetChanged();
                        }
                    }

                });
    // 移除天气地图
    private void RemoveMapFragment() {
        Iterator<Fragment> iterator = mFragments.iterator();
        while (iterator.hasNext()) {
            Fragment f = iterator.next();
            if (f instanceof MapFragment)
                iterator.remove();
        }
        Log.d("RossWeatherMap", "已移除天气地图");
        mMyFragmentPagerAdapter.notifyDataSetChanged();
        mViewPager.setCurrentItem(0);}

Bug出现了,删除后仍然显示地图并且可以操纵,使用Debug工具可以看到此时Fragments中已经没有MapFragment
Debug中mFragments中已经没有MapFragment

在百度查阅相关的问题发现这与ViewPager的缓存机制有关系,需要把FragmentPagerAdapter换成FragmentStatePagerAdapter才能使用,这里贴上原文地址:Android Viewpager动态删除Fragment解析
下面是修改后的FragmentStatePagerAdapter,之前用的是FragmentPagerAdapter

public class MyFragmentPagerAdapter extends FragmentStatePagerAdapter {

    private ArrayList<Fragment> mList;

    public MyFragmentPagerAdapter(FragmentManager fm, ArrayList<Fragment> list) {
        super(fm);
        mList = list;
        notifyDataSetChanged();
    }

    @Override
    public Fragment getItem(int arg0) {
        return mList.get(arg0);
    }

    @Override
    public int getItemPosition(Object object) {
        return PagerAdapter.POSITION_NONE;
    }
    @Override
    public int getCount() {
        return mList.size();
    }

}

注:引用stackoverflow牛人的解决说明:

The ViewPager doesn’t remove your fragments with the code above because it loads several views (or fragments in your case) into memory. In addition to the visible view, it also loads the view to either side of the visible one. This provides the smooth scrolling from view to view that makes the ViewPager so cool.
使用以上代码不会让ViewPager移除你的Fragments因为它把多个view(或者Fragment)加载到了内存中。它不仅仅加载了当前可见的view,同时也加载了当前可见view两边的view。正是因为提供了view与view之间流畅的滑动才使得viewpager那么酷。

To achieve the effect you want, you need to do a couple of things.
为了达成你想要的效果,你需要做以下几件事。

Change the FragmentPagerAdapter to a FragmentStatePagerAdapter. The reason for this is that the FragmentPagerAdapter will keep all the views that it loads into memory forever. Where the FragmentStatePagerAdapter disposes of views that fall outside the current and traversable views.
把FragmentPagerAdapter改成FragmentStatePagerAdapter。这么做的原因是FragmentPagerAdapter会一直持有它加载进内存的views。而FragmentStatePagerAdapter则会处理那些超出当前及可遍历的views的view。

Override the adapter method getItemPosition (shown below). When we call mAdapter.notifyDataSetChanged(); the ViewPager interrogates the adapter to determine what has changed in terms of positioning. We use this method to say that everything has changed so reprocess all your view positioning。
重写adap的getItemPosition方法。当我们调用notifyDataSetChanged()方法时ViewPager会让adapter来决定在view的位置上有什么变化。通过return PagerAdapter.POSITION_NONE;我们告诉ViewPager所有view都变化了,请ViewPager重新生成所有的view。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值