关于PagerAdapter changed the adapter's contents without calling PagerAdapter#notifyDataSetChanged!

偶尔遇到页面ViewPager滑动时发生了如下错误:

java.lang.IllegalStateException: The application's PagerAdapter changed the adapter's contents without calling PagerAdapter#notifyDataSetChanged! Expected adapter item count: 11, found: 22

该错误的出处位于viewPager的populate方法:

        final int pageLimit = mOffscreenPageLimit;
        final int startPos = Math.max(0, mCurItem - pageLimit);
        final int N = mAdapter.getCount();
        final int endPos = Math.min(N-1, mCurItem + pageLimit);

        if (N != mExpectedAdapterCount) {
            String resName;
            try {
                resName = getResources().getResourceName(getId());
            } catch (Resources.NotFoundException e) {
                resName = Integer.toHexString(getId());
            }
            throw new IllegalStateException("The application's PagerAdapter changed the adapter's" +
                    " contents without calling PagerAdapter#notifyDataSetChanged!" +
                    " Expected adapter item count: " + mExpectedAdapterCount + ", found: " + N +
                    " Pager id: " + resName +
                    " Pager class: " + getClass() +
                    " Problematic adapter: " + mAdapter.getClass());
        }

该方法会在很多地方被调用,比如ViewPager 每次翻页方法执行顺序:
dispatchKeyEvent->executeKeyEvent->arrowScroll->
pageLeft/pageRight->setCurrentItem->setCurrentItemInternal

在 setCurrentItemInternal 方法中,各种方法调用,会执行多次 populate() 方法,因此,会调用到多次 getCount()
来获取 N 的值

当 N != mExpectedAdapterCount 时便会发生如上错误,查阅源代码后发现 mExpectedAdapterCount 在dataSetChange方法出被赋值

 void dataSetChanged() {
     // This method only gets called if our observer is attached, so     mAdapter is non-null.
 
   final int adapterCount = mAdapter.getCount();
   mExpectedAdapterCount = adapterCount;
   // code here...
}

在 PagerAdapter 中调用 notifyDataSetChanged() 方法,数据更新的时候,mExpectedAdapterCount 会被重新赋值。

更新修改数据源一般是禁止在子线程中进行更新的。另外populate和notifyDataSetChanged两个方法都是在主线程中执行的,且有执行的先后顺序,所以如果发生了如上的错误,那么就需要查看数据修改和dataSetChange是否在主线程中连续的代码中执行,如果不是连续的主线程代码,那么在这两个动作间隔 viewPager的populdate 就有可能被调用,也就有可能发生上述错误

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 175,132评论 25 709
  • 本文出自 Eddy Wiki ,转载请注明出处:http://eddy.wiki/interview-java.h...
    eddy_wiki阅读 6,616评论 0 14
  • 2017年6月,我从某电影资讯类APP的主编岗位上辞职,结束了十年的上班族生活。 十年前,2007年,我刚刚从大学...
    亢蒙阅读 2,383评论 4 4
  • 很多时候想了解一个人,就是看TA的朋友圈。刷朋友圈已经成为大部分人生活的一部分。那该如何打造你的朋友圈呢? 1.乐...
    小小feng阅读 2,435评论 0 3
  • 给自己一个全新的选择之前都是要经过深思熟虑的思考,并且用自己最真的心去感受那个环境,是不是真的是你所要选择...
    菇凉是个爷阅读 1,930评论 1 0