公司做醫療産品的,顯示操作用的是android,是以我就用上下兩個部分大緻是固定的,隻有中間會有6個頁面的切換,其中會有兩個使用者的切換,即普通使用者和管理者使用者,圖檔可以大緻展示一下
其它頁面是相同的,就這兩個頁面不一樣,下面的是管理者使用者,一想到其它頁面一樣的,中間就用了一個ViewPager,然後為了緩存多個頁面,用到了FragmentStatePagerAdapter,然後通過setOffscreenPageLimit(6)最多緩存了6個頁面,這樣一下,就不用擔心每個頁面的fragment的聲明周期對我項目的影響了,這個界面可能沒有,但是其它界面的檢測什麼的,線程和Ui比較複雜,容易受fragment聲明周期影響而crash。
但是這個裡有個奇怪的要求,管理者使用者的項目設定界面的功能竟然不是全的,有兩個在普通使用者那邊,這個設計我也很納悶,不過,還是得做啊,之後,就遇到了題目所說的問題,notifyDataSetChanged雖然會有頁面的增多和減少,但是,項目界面就是不重新整理。
然後找了度娘和谷哥,出來的答案大多指向同一篇文章http://www.cnblogs.com/dancefire/archive/2013/01/02/why-notifyDataSetChanged-does-not-work.html,略微看了一遍,照着上面方法試了,報錯,依舊不得其要領,然後自己去看了下源碼,解決了,分享并記住這個問題,免得以後再犯錯
先進入notifyDataSetChanged
發現這句,mObservable,看名字,觀察者,應該就是用來實時監測viewPager綁定資料源的變化的,再進入notifychanged方法
發現一個周遊,這個周遊會去調用mObservers中的每一個元素的變化,我們再進入onChanged,
到了,這裡,發現onChanged隻是一個抽象類中的方法,,既然會調用,肯定會被重寫咯,找了一圈,在viewPager中的内部内繼承了,
躲的還是蠻深的,不過這還沒有找到我們需要關注的地方,那就繼續找,dataSetChanged
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();
}
}
這裡就是我們需要關注的地方了,一看這麼多,确實有點頭疼,不過,我們隻關注重點,看第13行,有句
final int newPos = mAdapter.getItemPosition(ii.object);
這裡就調用的了我們的adapter中的getItemPosition,我們再看看getItemPosition會傳回什麼,會接收什麼,複寫fragmentStatePagerAdapter中的getItemPosition方法,發現隻會傳回父類中的方法
接着看父類中的方法
再看看POSITION_UNCHANGED是幹嘛用的,
馬丹,這下總算是明白了,這裡一直return POSITION_UNCHANGED;
return一個“未改變”的标志給dataSetChanged()中,它當然打死都不更新咯,請看dataSetChanged()中的第15-17行
魂淡,竟然知道原因了,那就好做了,直接将要重新整理的頁面 return POSITION_NONE
@Override
public int getItemPosition(Object object) {
if (object.getClass().getName().equals(ProjectFragment.class.getName())
|| object.getClass().getName().equals(ProjectFragment2.class.getName())) {
return POSITION_NONE;
}
return super.getItemPosition(object);
}