关于FragmentPagerAdapter无法更新Fragment数的问题

需求描述:学习中心—-有个两个pager,一个参加的课程,一个参加的微专业。每个pager要求用fragment实现。最外层是一个ViewPager控件。可以实现下拉刷新功能,如果微专业列表为null,只显示参加的课程;不为null则显示两个pager页。

分析需求,这里需要实现的是FragmentPagerAdapter.notifyDataSetChange()可以更新fragment的数量,有时候可以显示两个,有时候一个,每次刷新可能都会不同。

简单的用正常手段去实现ViewPager+FragmentPagerAdapter去实现,发现无法做到刷新更新fragment的数量的问题。这里需要结合源码做一些特殊处理。

先看我写的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。当需要remove掉其中一个Fragment的时候,让getItemPosition返回POSITION_NONE,意思是该位置的pager已经不存在了,需要destoryItemview方法,然后重新getItem。默然返回的是POSITION_UNCHANGED,pager没变化,不会刷新当前的pager。

做完这一步之后发现,的确刷新后可以隐藏掉该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,发现之前remove的fragment不为null,然后又将之前remove掉的fragment attach到view pager里面。但是界面数据并没有刷新,还是用remove前的数据。

所以,我总结出的方法就是,如果要更新FragmentPagerAdapter里的fragment,不仅仅是remove掉该Fragment,还应该给该fragment赋null。这样如果需要再次显示该fragment就不会出问题。当然前提是你有用POSITION_NONE去做处理。这还得根据具体业务需求来做。

细心的朋友可能会发现我这里重写了下面的方法

@Override

public longgetItemId(intposition) {

returnmPageList.get(position).getFragmentId();

}

系统默认返回的是position。

之前有个需求要求参加前的fragment pagers是“介绍”、“评价”,点击参加后fragment pagers要变成“目录”,“公告”。再退选又变回来。这些pagers都是不同的fragment实现的。在当前activity去做更新。

好吧,如果遇到这种需求,你会发现上面重写的方法自己实现会帮助到你。因为源码里的实现是

longitemId =this.getItemId(position);

String name = makeFragmentName(container.getId(), itemId);

Fragment fragment =this.mFragmentManager.findFragmentByTag(name);

具体不多说,还是多看源码,根据具体需求设计更合适的实现方案。

你可能感兴趣的:(关于FragmentPagerAdapter无法更新Fragment数的问题)