1.问题由来:项目的旧有代码中有一个Banner使用了Fragment+FragmentPagerAdapter的方式实现,当数据刷新调用adapter的NotifyDatasetChanged方法后,发现Fragment并没有重走任何生命周期方法,Fragment实例也没有重新创建,无法实现数据的刷新
2.思考:FragmentPagerAdapter中的getItem方法和initiateItem方法都没有被调用,查阅了一些资料 http://blog.youkuaiyun.com/zqs62761130/article/details/46289739 ,
文章指出了NotifyDatasetChanged方法调用后的机制
因此,对于 FragmentPagerAdapter 的解决方案就是,分别重载 getItem() 以及 instantiateItem() 。getItem() 只用于生成新的与数据无关的 Fragment;而 instantiateItem() 函数则先调用父类中的 instantiateItem() 取得所对应的 Fragment 对象,然后,根据对应的数据,调用该对象对应的方法进行数据设置。
当然,不要忘记重载 getItemPosition() 函数,返回 POSITION_NONE,这个两个类的解决方案都需要的。二者不同之处在于,FragmentStatePagerAdapter 在会在因 POSITION_NONE 触发调用的 destroyItem() 中真正的释放资源,重新建立一个新的 Fragment;而 FragmentPagerAdapter 仅仅会在 destroyItem() 中 detach 这个 Fragment,在 instantiateItem() 时会使用旧的 Fragment,并触发 attach,因此没有释放资源及重建的过程。
3.解决方法:
重写getItemPosition方法,使得数据刷新后能够调用initiateItem方法,在该方法中为Fragment重新设置数据,但是这里不能使用setArgument的方式,因为FragmentPagerAdapter中Fragment不会销毁重建,而setArgument只在Fragment没有被添加到FragmentManager之前才会有效,所以需要其他方式设置数据(直接设置数据bean等)。
4.一个例子
private static class BannerAdapter extends FragmentPagerAdapter {
List<ProjectBean> mData;
BannerAdapter(FragmentManager fm) {
super(fm);
mData = new ArrayList<>();
}
void update(List<ProjectBean> data) {
mData.clear();
mData.addAll(data);
notifyDataSetChanged();
}
@Override
public Fragment getItem(int position) {
return BannerFragment.instance(mData.get(position));
}
@Override
public int getCount() {
return mData.size();
}
}
public static class BannerFragment extends Fragment {
static BannerFragment instance(ProjectBean bean) {
BannerFragment fragment = new BannerFragment();
Bundle bundle = new Bundle();
bundle.putSerializable("data", bean);
fragment.setArguments(bundle);
return fragment;
}
private TextView mTitle;
private TextView mIncome;
private TextView mIncomeDesc;
private TextView mTimeDesc;
private TextView mLabel1;
private TextView mLabel2;
private TextView mMoneyDesc;
private TextView mTime;
private TextView mMoney;
private ProgressBar mProgressBar;
private ImageView mTag;
private ConstraintLayout mLayout;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_banner, container, false);
initView(rootView);
initData(getArguments(), rootView);
mLayout.setBackgroundResource(R.mipmap.list_bg_red);
return rootView;
}
private void initData(Bundle arguments, View rootView) {
ProjectBean item = (ProjectBean) arguments.getSerializable("data");
mTitle.setText(item.title);
mIncome.setText(item.userInterest + "%");
if (item.userRaiseInterest <= 0) {
mLabel1.setVisibility(View.GONE);
} else {
mLabel1.setText("已加" + item.userRaiseInterest + "%");
}
if (TextUtils.isEmpty(item.giveoutInterestDesc)) {
mLabel2.setVisibility(View.GONE);
} else {
mLabel2.setText(item.giveoutInterestDesc);
}
mTime.setText(item.duration + "天");
int remind = (int) (item.amount * (100 - item.percent) / 100);
mMoney.setText(remind + "元");
mProgressBar.setProgress(((int) item.percent));
rootView.setOnClickListener(v -> Skip.toProjectDetail(v.getContext(), item.id));
switch (getLabelType(item)) {
case -1:
mTag.setImageResource(R.drawable.tag_full);
break;
case -2:
mTag.setImageResource(R.drawable.tag_repayment);
break;
case 1:
mTag.setImageResource(R.drawable.tag_1);
break;
case 2:
mTag.setImageResource(R.drawable.tag_2);
break;
case 3:
mTag.setImageResource(R.drawable.tag_3);
break;
case 4:
mTag.setImageResource(R.drawable.tag_4);
break;
case 5:
mTag.setImageResource(R.drawable.tag_5);
break;
case 6:
mTag.setImageResource(R.drawable.tag_6);
break;
case 9:
mTag.setImageResource(R.drawable.tag_9);
break;
}
}
private int getLabelType(ProjectBean item) {
switch (item.categoryId) {
case 2:
return -1;
case 3:
return -2;
default:
return item.newPreferential;
}
}
private void initView(@NonNull final View itemView) {
mTitle = (TextView) itemView.findViewById(R.id.title);
mLayout = (ConstraintLayout) itemView.findViewById(R.id.layout);
mIncome = (TextView) itemView.findViewById(R.id.income);
mIncomeDesc = (TextView) itemView.findViewById(R.id.incomeDesc);
mTimeDesc = (TextView) itemView.findViewById(R.id.timeDesc);
mLabel1 = (TextView) itemView.findViewById(R.id.label1);
mLabel2 = (TextView) itemView.findViewById(R.id.label2);
mMoneyDesc = (TextView) itemView.findViewById(R.id.moneyDesc);
mTime = (TextView) itemView.findViewById(R.id.time);
mMoney = (TextView) itemView.findViewById(R.id.money);
mProgressBar = (ProgressBar) itemView.findViewById(R.id.progressBar);
mTag = (ImageView) itemView.findViewById(R.id.tag);
}
}