需求描述:學(xué)習(xí)中心—-有個兩個pager师脂,一個參加的課程,一個參加的微專業(yè)。每個pager要求用fragment實現(xiàn)吃警。最外層是一個ViewPager控件糕篇。可以實現(xiàn)下拉刷新功能酌心,如果微專業(yè)列表為null拌消,只顯示參加的課程;不為null則顯示兩個pager頁安券。
分析需求墩崩,這里需要實現(xiàn)的是FragmentPagerAdapter.notifyDataSetChange()可以更新fragment的數(shù)量,有時候可以顯示兩個侯勉,有時候一個鹦筹,每次刷新可能都會不同。
簡單的用正常手段去實現(xiàn)ViewPager+FragmentPagerAdapter去實現(xiàn)址貌,發(fā)現(xiàn)無法做到刷新更新fragment的數(shù)量的問題铐拐。這里需要結(jié)合源碼做一些特殊處理。
先看我寫的adapter:
private classCourseEnrolledFragmentAdapterextendsFragmentPagerAdapter {
publicCourseEnrolledFragmentAdapter(FragmentManager fm) {
super(fm);
}
@Override
publicFragment getItem(inti) {
if(i <mPageList.size()) {
returnmPageList.get(i);
}
return null;
}
@Override
public intgetCount() {
returnmPageList.size();
}
@Override
public intgetItemPosition(Object object) {
if(mPageList!=null&& !mPageList.isEmpty()) {
if(!mPageList.contains(object)) {
returnPOSITION_NONE;
}
}
returnPOSITION_UNCHANGED;
}
@Override
public longgetItemId(intposition) {
returnmPageList.get(position).getFragmentId();
}
@Override
publicCharSequence getPageTitle(intposition) {
if(mTabNames!=null&&mTabNames.length> position) {
returnmTabNames[position];
}
return super.getPageTitle(position);
}
}
這里我重寫了getItemPosition方法练对,mPageList是一個fragment的ArrayList遍蟋。當(dāng)需要remove掉其中一個Fragment的時候,讓getItemPosition返回POSITION_NONE螟凭,意思是該位置的pager已經(jīng)不存在了匿值,需要destoryItemview方法,然后重新getItem赂摆。默然返回的是POSITION_UNCHANGED,pager沒變化钟些,不會刷新當(dāng)前的pager烟号。
做完這一步之后發(fā)現(xiàn),的確刷新后可以隱藏掉該fragment政恍,
mPageList.remove(mFragmentMicroSpecial);
mFragmentAdapter.notifyDataSetChanged();
但是如果再刷新又需要顯示該fragment的話汪拥,然后就出問題了。因為在FragmentPagerAdapter源碼里面
publicObject instantiateItem(ViewGroup container,intposition) {
if(this.mCurTransaction ==null) {
this.mCurTransaction =this.mFragmentManager.beginTransaction();
}
longitemId =this.getItemId(position);
String name = makeFragmentName(container.getId(), itemId);
Fragment fragment =this.mFragmentManager.findFragmentByTag(name);
if(fragment !=null) {
this.mCurTransaction.attach(fragment);
}else{
fragment =this.getItem(position);
this.mCurTransaction.add(container.getId(), fragment, makeFragmentName(container.getId(), itemId));
}
if(fragment !=this.mCurrentPrimaryItem) {
fragment.setMenuVisibility(false);
fragment.setUserVisibleHint(false);
}
returnfragment;
}
findFragmentByTag的方式去查找之前的fragment篙耗,發(fā)現(xiàn)之前remove的fragment不為null迫筑,然后又將之前remove掉的fragment attach到view pager里面。但是界面數(shù)據(jù)并沒有刷新宗弯,還是用remove前的數(shù)據(jù)脯燃。
所以,我總結(jié)出的方法就是蒙保,如果要更新FragmentPagerAdapter里的fragment辕棚,不僅僅是remove掉該Fragment,還應(yīng)該給該fragment賦null。這樣如果需要再次顯示該fragment就不會出問題逝嚎。當(dāng)然前提是你有用POSITION_NONE去做處理扁瓢。這還得根據(jù)具體業(yè)務(wù)需求來做。
細(xì)心的朋友可能會發(fā)現(xiàn)我這里重寫了下面的方法
@Override
public longgetItemId(intposition) {
returnmPageList.get(position).getFragmentId();
}
系統(tǒng)默認(rèn)返回的是position补君。
之前有個需求要求參加前的fragment pagers是“介紹”引几、“評價”,點(diǎn)擊參加后fragment pagers要變成“目錄”挽铁,“公告”伟桅。再退選又變回來。這些pagers都是不同的fragment實現(xiàn)的屿储。在當(dāng)前activity去做更新贿讹。
好吧,如果遇到這種需求够掠,你會發(fā)現(xiàn)上面重寫的方法自己實現(xiàn)會幫助到你民褂。因為源碼里的實現(xiàn)是
longitemId =this.getItemId(position);
String name = makeFragmentName(container.getId(), itemId);
Fragment fragment =this.mFragmentManager.findFragmentByTag(name);
具體不多說惯雳,還是多看源碼弧关,根據(jù)具體需求設(shè)計更合適的實現(xiàn)方案。