Android PagerAdapter notifyDatasetChanged

forget to call notifyDatasetChanged 错误

这几天一直在完善之前自己的写的Android应用。想用ViewPager让之前界面能够滑动阅读。但是滑动过程中,经常会莫名其妙地遇到一个问题。莫名其妙地提示ViewPager expected 10 counts,but found 20. forget to call notifyDatasetChanged. 意思很明显,就是ViewPager的数据集改变了,但是我却忘了去通过notifyDatasetChanged去通知PagerAdapter数据已经更新了。但是我其实在那个页面压根没有去更新数据。不过根据提示显然是因为哪个地方改变了数据的数量。还好我动态更新数据的地方不多。检查一下代码,根据自己的思路,立刻发现了问题。我会在已经载入当前列表的时候,去服务器取下一个列表。这样在我取完下一个列表的时候,数据就变了。然后就出现那个问题了。

虽然没怎么浪费时间就解决了问题,但是在面对多个线程数据共享的时候确实得增加一些额外的考虑。PagerAdapter的数据如果改变,是需要调用notifyDatasetChanged方法的。多线程的共享需要考虑同步的问题,这个同步不仅仅是一个synchronize就能够避免的,每个线程都需要去预防共享的数据被另外一个线程更改了。

ViewPager与Fragment

我在使用ViewPager的时候,使用了FragmentStatePagerAdapter作为它的Adapter,因为会有很多Fragment,如何从ViewPager控制它的Fragment就成了一个问题。

当然,直接保存ViewPager的所有Fragment似乎就能够控制了,但是这实在是不科学,保存起来太耗空间。而实际上ViewPager每次只有几个View保存着。当前显示的View以及前后几个View,在这之外的View都会被destory掉。这样能够很好地控制占用的内存。

但是幸运地是FragmentActivity的FragmentManager提供了一个getFragments的方法,该方法能够获取当前所有的Fragment。这样问题就解决了。获取Activity中所有的Fragment,然后判断是不是FragmentStatePagerAdapter的Fragment。这样ViewPager就能够直接控制它的Fragment Item了。

对于FragmentPagerAdapter与FragmentStatePagerAdapter的区别,FragmentPagerAdapter会对每一个Fragment进行缓存,而FragmentStatePagerAdapter不会。两个的使用方法是一样的。

notifyDatasetChanged做了什么工作?

每个Adapter都会有private DataSetObservable mObservable = new DataSetObservable(); 一个DataSetObservable观察者。这个观察者可以注册registerDataSetObserver。而notifyDatasetChanged函数做的就是通知注册这,我的数据已经改变了。

这样就给了ViewPager监听Adapter数据集变化的机会。在ViewPager的setAdapter中,有下面这段代码:

    431        if (mAdapter != null) {
    432            if (mObserver == null) {
    433                mObserver = new PagerObserver();
    434            }
    435            mAdapter.registerDataSetObserver(mObserver);
    436            mPopulatePending = false;
    437            final boolean wasFirstLayout = mFirstLayout;
    438            mFirstLayout = true;
    439            mExpectedAdapterCount = mAdapter.getCount();
    440            if (mRestoredCurItem >= 0) {
    441                mAdapter.restoreState(mRestoredAdapterState, mRestoredClassLoader);
    442                setCurrentItemInternal(mRestoredCurItem, false, true);
    443                mRestoredCurItem = -1;
    444                mRestoredAdapterState = null;
    445                mRestoredClassLoader = null;
    446            } else if (!wasFirstLayout) {
    447                populate();
    448            } else {
    449                requestLayout();
    450            }
    451        }

在上面的代码中,注册了数据集变化的观察者。而notifyDatasetChanged就是通知观察者。


探究

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: PagerAdapterAndroid中的一个抽象类,用于管理多个视图之间的切换。它是ViewPager的一个必需组件,用于在ViewPager中显示多个视图。PagerAdapter负责从数据集中获取每个页面的视图,并将其添加到ViewPager中。同时,PagerAdapter还管理视图的销毁和重建,以确保内存使用效率。PagerAdapter有几个具体的子类,包括FragmentPagerAdapter和FragmentStatePagerAdapter,它们分别用于管理Fragment和视图的切换。 ### 回答2: PagerAdapterAndroid中的一个类,用于管理和显示多个界面,常用于TabLayout与ViewPager的结合中。它是PagerAdapter接口的实现类,实现了其中的方法。 PagerAdapter可以用于不同类型的界面切换,例如Fragment、View等。通过在PagerAdapter中重写getItem()方法,可以返回对应位置的界面对象。getPageTitle()方法可以返回每个界面的标题。 PagerAdapter有三个重要的方法:getCount()、instantiateItem()和destroyItem()。 getCount()方法返回ViewPager中所包含的界面数量。instantiateItem()方法用于实例化ViewPager中特定位置的界面,并将其添加到ViewPager中。destroyItem()方法用于销毁ViewPager中特定位置的界面。 PagerAdapter还提供了一些其他方法,如isViewFromObject()用于判断一个界面对象是否与当前视图相关联;getItemPosition()用于获取界面对象的位置;finishUpdate()用于完成界面的更新。 PagerAdapter可以根据需求进行自定义,实现不同的界面展示效果。例如,可以自定义PagerAdapter的子类,重写isViewFromObject()方法来实现判断不同界面是否相等的逻辑。 在使用PagerAdapter时,需要创建一个PagerAdapter的实例,并将其设置给ViewPager。然后,通过ViewPager.setCurrentItem()方法可以切换到指定位置的界面。 总而言之,PagerAdapterAndroid中用于管理和显示多个界面的工具,可以实现界面切换、标题显示等功能,并且可以根据需求进行自定义。 ### 回答3: PagerAdapterAndroid 中的一个适配器类,主要用于在 ViewPager 中展示多个页面。它是 PagerAdapter 类的子类,用于为 ViewPager 提供数据和视图。 PagerAdapter 提供了以下几种方法来管理 ViewPager 中的页面: 1. getCount() 方法:用于获取 ViewPager 中页面的总数。 2. instantiateItem() 方法:用于创建并返回指定位置的页面对象。 3. destroyItem() 方法:用于销毁指定位置的页面对象。 4. getPageTitle() 方法:用于获取指定位置页面的标题,用于设置 ViewPager 的标题。 5. isViewFromObject() 方法:用于判断指定的对象是否是页面的视图。 使用 PagerAdapter 主要包括以下几个步骤: 1. 创建一个继承 PagerAdapter 的自定义适配器类。 2. 实现适配器类中的 getCount() 方法,返回页面的总数。 3. 实现 instantiateItem() 方法,用于创建并返回指定位置的页面对象。 4. 实现 destroyItem() 方法,用于销毁指定位置的页面对象。 5. 实现 getPageTitle() 方法,用于设置页面的标题。 6. 实现 isViewFromObject() 方法,用于判断指定的对象是否是页面的视图。 7. 将适配器对象设置给 ViewPager。 通过以上步骤,我们就可以在 ViewPager 中展示多个页面,并可以自定义这些页面的数据和视图。通过滑动 ViewPager,我们可以切换不同的页面,从而实现了页面的左右滑动切换效果。PagerAdapterAndroid 开发中被广泛应用于多个页面的展示场景,比如图片轮播、引导页等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值