有关viewPager item数量相同数据不同时显示问题
2016-12-16 17:31
260 查看
当我们使用viewPager 设置数据后,如果只是更新了数据,但数据项数没变,那么当我们调用notifyDataSetChanged();里面的内容并不会刷新
跟踪下ViewPager的源码,主要是在下面这个函数
void dataSetChanged() {
// This method only gets called if our observer is attached, so mAdapter is non-null.
final int adapterCount = mAdapter.getCount();
mExpectedAdapterCount = adapterCount;
boolean needPopulate = mItems.size() < mOffscreenPageLimit * 2 + 1 &&
mItems.size() < adapterCount;
int newCurrItem = mCurItem;
boolean isUpdating = false;
for (int i = 0; i < mItems.size(); i++) {
final ItemInfo ii = mItems.get(i);
final int newPos = mAdapter.getItemPosition(ii.object);
if (newPos == PagerAdapter.POSITION_UNCHANGED) {
continue;
}
if (newPos == PagerAdapter.POSITION_NONE) {
mItems.remove(i);
i--;
if (!isUpdating) {
mAdapter.startUpdate(this);
isUpdating = true;
}
mAdapter.destroyItem(this, ii.position, ii.object);
needPopulate = true;
if (mCurItem == ii.position) {
// Keep the current item in the valid range
newCurrItem = Math.max(0, Math.min(mCurItem, adapterCount - 1));
needPopulate = true;
}
continue;
}
if (ii.position != newPos) {
if (ii.position == mCurItem) {
// Our current item changed position. Follow it.
newCurrItem = newPos;
}
ii.position = newPos;
needPopulate = true;
}
}
if (isUpdating) {
mAdapter.finishUpdate(this);
}
Collections.sort(mItems, COMPARATOR);
if (needPopulate) {
// Reset our known page widths; populate will recompute them.
final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (!lp.isDecor) {
lp.widthFactor = 0.f;
}
}
setCurrentItemInternal(newCurrItem, false, true);
requestLayout();
}
}这里主要是needPopulate,如果是第一次刷新且有数据,mItems为0,adapterCount为当前要显示的item的数目(假设大于0),所有needPopulate为true进而调用setCurrentItemInternal
void setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int velocity) {
if (mAdapter == null || mAdapter.getCount() <= 0) {
setScrollingCacheEnabled(false);
return;
}
if (!always && mCurItem == item && mItems.size() != 0) {
setScrollingCacheEnabled(false);
return;
}
if (item < 0) {
item = 0;
} else if (item >= mAdapter.getCount()) {
item = mAdapter.getCount() - 1;
}
final int pageLimit = mOffscreenPageLimit;
if (item > (mCurItem + pageLimit) || item < (mCurItem - pageLimit)) {
// We are doing a jump by more than one page. To avoid
// glitches, we want to keep all current pages in the view
// until the scroll ends.
for (int i=0; i<mItems.size(); i++) {
mItems.get(i).scrolling = true;
}
}
final boolean dispatchSelected = mCurItem != item;
if (mFirstLayout) {
// We don't have any idea how big we are yet and shouldn't have any pages either.
// Just set things up and let the pending layout handle things.
mCurItem = item;
if (dispatchSelected) {
dispatchOnPageSelected(item);
}
requestLayout();
} else {
populate(item);
scrollToItem(item, smoothScroll, velocity, dispatchSelected);
}
}第一次mFirstLayout为true,调用requestLayout最终会调用到它的onMeasureonMeasure又调用populate,它又会执行
if (curItem == null && N > 0) {
curItem = addNewItem(mCurItem, curIndex);
}
这里会调用adapter的initstantiateItem实例化一个item.
回到前面dataSetChanged,如果item里面已经有数据,并且数据项
boolean needPopulate = mItems.size() < mOffscreenPageLimit * 2 + 1 &&
mItems.size() < adapterCount;如果前面存在的item(mItem)的数量大于adapterCount,则needPopulate为false,不会刷新
目前解决的办法是每次拉到数据的时候重新new一个adapter并且设置到viewPager
跟踪下ViewPager的源码,主要是在下面这个函数
void dataSetChanged() {
// This method only gets called if our observer is attached, so mAdapter is non-null.
final int adapterCount = mAdapter.getCount();
mExpectedAdapterCount = adapterCount;
boolean needPopulate = mItems.size() < mOffscreenPageLimit * 2 + 1 &&
mItems.size() < adapterCount;
int newCurrItem = mCurItem;
boolean isUpdating = false;
for (int i = 0; i < mItems.size(); i++) {
final ItemInfo ii = mItems.get(i);
final int newPos = mAdapter.getItemPosition(ii.object);
if (newPos == PagerAdapter.POSITION_UNCHANGED) {
continue;
}
if (newPos == PagerAdapter.POSITION_NONE) {
mItems.remove(i);
i--;
if (!isUpdating) {
mAdapter.startUpdate(this);
isUpdating = true;
}
mAdapter.destroyItem(this, ii.position, ii.object);
needPopulate = true;
if (mCurItem == ii.position) {
// Keep the current item in the valid range
newCurrItem = Math.max(0, Math.min(mCurItem, adapterCount - 1));
needPopulate = true;
}
continue;
}
if (ii.position != newPos) {
if (ii.position == mCurItem) {
// Our current item changed position. Follow it.
newCurrItem = newPos;
}
ii.position = newPos;
needPopulate = true;
}
}
if (isUpdating) {
mAdapter.finishUpdate(this);
}
Collections.sort(mItems, COMPARATOR);
if (needPopulate) {
// Reset our known page widths; populate will recompute them.
final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (!lp.isDecor) {
lp.widthFactor = 0.f;
}
}
setCurrentItemInternal(newCurrItem, false, true);
requestLayout();
}
}这里主要是needPopulate,如果是第一次刷新且有数据,mItems为0,adapterCount为当前要显示的item的数目(假设大于0),所有needPopulate为true进而调用setCurrentItemInternal
void setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int velocity) {
if (mAdapter == null || mAdapter.getCount() <= 0) {
setScrollingCacheEnabled(false);
return;
}
if (!always && mCurItem == item && mItems.size() != 0) {
setScrollingCacheEnabled(false);
return;
}
if (item < 0) {
item = 0;
} else if (item >= mAdapter.getCount()) {
item = mAdapter.getCount() - 1;
}
final int pageLimit = mOffscreenPageLimit;
if (item > (mCurItem + pageLimit) || item < (mCurItem - pageLimit)) {
// We are doing a jump by more than one page. To avoid
// glitches, we want to keep all current pages in the view
// until the scroll ends.
for (int i=0; i<mItems.size(); i++) {
mItems.get(i).scrolling = true;
}
}
final boolean dispatchSelected = mCurItem != item;
if (mFirstLayout) {
// We don't have any idea how big we are yet and shouldn't have any pages either.
// Just set things up and let the pending layout handle things.
mCurItem = item;
if (dispatchSelected) {
dispatchOnPageSelected(item);
}
requestLayout();
} else {
populate(item);
scrollToItem(item, smoothScroll, velocity, dispatchSelected);
}
}第一次mFirstLayout为true,调用requestLayout最终会调用到它的onMeasureonMeasure又调用populate,它又会执行
if (curItem == null && N > 0) {
curItem = addNewItem(mCurItem, curIndex);
}
ItemInfo addNewItem(int position, int index) { ItemInfo ii = new ItemInfo(); ii.position = position; ii.object = mAdapter.instantiateItem(this, position); ii.widthFactor = mAdapter.getPageWidth(position); if (index < 0 || index >= mItems.size()) { mItems.add(ii); } else { mItems.add(index, ii); } return ii; }
这里会调用adapter的initstantiateItem实例化一个item.
回到前面dataSetChanged,如果item里面已经有数据,并且数据项
boolean needPopulate = mItems.size() < mOffscreenPageLimit * 2 + 1 &&
mItems.size() < adapterCount;如果前面存在的item(mItem)的数量大于adapterCount,则needPopulate为false,不会刷新
目前解决的办法是每次拉到数据的时候重新new一个adapter并且设置到viewPager
相关文章推荐
- Android开发笔记 ViewPager 嵌套 RecyclerView instantiateItem数据初始化错位问题
- viewpager+fragment联网加载数据无显示以及预加载问题解决
- 问题记录 170228 viewpager同时显示前后,即同时显示三张图
- Fragment popupstack之后viewpager中的fragment不显示数据的问题
- 关于ViewPager嵌套Fragment,第二次加载数据不显示问题
- ViewPager嵌套RecycleView(Fragment作为数据源)来展示10条数据,每个Item显示的内容是(Android软件开发工程师)(用自定义的Adapter 实现
- Viewpage的.setCurrentItem 导致UI线程的执行阻塞问题 广告轮播 数据加载后填充viewpagerAdapter
- 使用多个ViewPager+Fragment布局相同情况下Fragment不显示问题
- 关于ViewPager嵌套Fragment,第二次加载数据不显示问题
- fragment嵌套viewpager嵌套fragment第二次加载数据不显示问题
- 一个页面上显示ViewPager的多个item问题
- android 获取网络数据,回传到本地用TextView显示乱码问题解决方法
- android scrollView 内嵌ViewPager或Gallery等水平滑动控件冲突问题解决实现同时滑动
- 解决fragment+viewpager第二次进入的时候没有数据的问题
- 解决fragment+viewpager第二次进入的时候没有数据的问题
- 有关ViewPager的使用及解决Android下ViewPager和PagerAdapter中调用notifyDataSetChanged失效的问题
- Viewpager+fragment数据更新问题
- Android 当可缩放的View用ViewPager显示时 左右滑动冲突问题
- 关于ViewPager 只显示一半的问题
- 有关 在self.navigationItem.titleView 中增加视图的问题