关于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 就有可能被调用,也就有可能发生上述错误

你可能感兴趣的:(关于PagerAdapter changed the adapter's contents without calling PagerAdapter#notifyDataSetChanged!)