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
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值