首页 > 解决方案 > Viewpager 内的多个 Recyclerview 问题

问题描述

我有一个Viewpager里面有两个标签。选项卡是卡片和收藏卡片。我在两个选项卡中使用相同的片段。该片段包含一个RecyclerView我动态更新的。我将元素一个一个地添加到两个选项卡中。我首先将元素完全添加到第一个选项卡(卡片选项卡),完成后我将元素添加到第二个选项卡(最喜欢的卡片选项卡)。我的问题是当我将元素添加到第二个选项卡时,我RecyclerView内部的第一个选项卡也会更新。现在第一个选项卡中的元素RecyclerView是现有元素加上我在第二个选项卡中添加的元素的总和。ViewPager我在两个选项卡中设置了两个不同的 ArrayList 。但是当getItemCount()在第一个选项卡中调用时RecyclerView, ArrayList 具有我在第二个选项卡中添加的元素。

RecyclerView在两个选项卡中都使用带有 a 的相同片段。当我想更新单个选项卡时,我会调用notifyDatasetChanged(). ViewPager所以每次RecyclerView片段内部都会重新初始化。

这是我的 Viewpager 适配器

public class ViewPagerWebCardsAdapter extends FragmentStatePagerAdapter {

private ArrayList<WebCardBaseResponseModel> webCardDetailList;
private ArrayList<WebCardBaseResponseModel> followingWebCardList;
private Context context;
private boolean isEmptyFavoriteWebcardList;
private boolean isEmptyWebcardsList;

public ViewPagerWebCardsAdapter(FragmentManager fm, ArrayList<WebCardBaseResponseModel> webCardDetailList,
                                ArrayList<WebCardBaseResponseModel> followingWebCardList,
                                Context context) {
    super(fm);
    this.webCardDetailList = webCardDetailList;
    this.followingWebCardList = followingWebCardList;
    this.context = context;
}

public void updateWebCardLists( ArrayList<WebCardBaseResponseModel> webCardDetailList,
                                ArrayList<WebCardBaseResponseModel> followingWebCardList) {
    this.webCardDetailList = webCardDetailList;
    this.followingWebCardList = followingWebCardList;
    notifyDataSetChanged();
}

public void setEmptyFollowingCardsFragment() {
    isEmptyFavoriteWebcardList = true;
    notifyDataSetChanged();
}

public void setEmptyWebCardsFragment() {
    isEmptyWebcardsList = true;
    notifyDataSetChanged();
}

@Override
public Fragment getItem(int position) {
    if(position == 0) {
        WebCardListFragment webCardListFragment = new WebCardListFragment();
        webCardListFragment.setWebCardDetailList(webCardDetailList);
        webCardListFragment.setEmptyListFragment(isEmptyWebcardsList);
        return webCardListFragment;
    } else {
        WebCardListFragment webCardListFragment = new WebCardListFragment();
        webCardListFragment.setWebCardDetailList(followingWebCardList);
        webCardListFragment.setEmptyListFragment(isEmptyFavoriteWebcardList);
        webCardListFragment.setAsFavoritesList();
        return webCardListFragment;
    }
}

@Override
public int getCount() {
    return Constants.NUMBER_TWO;
}

@Override
public int getItemPosition(Object object) {
    return POSITION_NONE;
}

@Override
public CharSequence getPageTitle(int position) {
    if(position == 0) {
        return context.getString(R.string.webcards);
    } else {
        return context.getString(R.string.favorite);
    }
}

}

这是我的卡片片段

public class WebCardListFragment extends Fragment {

@BindView(R.id.web_card_recycler_view)
RecyclerView mWebCardDetailRecyclerView;

@BindView(R.id.tv_description)
TextView tvDescription;

@BindView(R.id.progress_bar)
public ProgressBar progressBar;

private WebCardListAdapter mWebCardListAdapter;
ArrayList<WebCardBaseResponseModel> mWebCardDetailList;
WebCardActivity activity;
private boolean isFavorites;
private boolean isEmptyListFragment;

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    activity = (WebCardActivity) context;
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

public void setWebCardDetailList(ArrayList<WebCardBaseResponseModel> mWebCardDetailList) {
    this.mWebCardDetailList = mWebCardDetailList;
}

public void setAsFavoritesList() {
    this.isFavorites = true;
}

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_webcard_list, container, false);
    ButterKnife.bind(this, view);
    initView();

    return view;
}

private void initView() {
    if(isFavorites) {
        tvDescription.setText(getString(R.string.select_webcard_to_share));
    }

    RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(activity);
    mWebCardDetailRecyclerView.setLayoutManager(mLayoutManager);
    mWebCardDetailRecyclerView.setHasFixedSize(true);
    mWebCardDetailRecyclerView.setItemAnimator(new DefaultItemAnimator());
    if(mWebCardDetailList != null && mWebCardDetailList.size() > 0) {
        progressBar.setVisibility(View.GONE);
        tvDescription.setVisibility(View.VISIBLE);
        mWebCardListAdapter = new WebCardListAdapter(activity, mWebCardDetailList, isFavorites);
    }
    if(isEmptyListFragment) {
        progressBar.setVisibility(View.GONE);
        tvDescription.setVisibility(View.VISIBLE);
        tvDescription.setText(getString(R.string.no_webcards_to_list));
    }
    mWebCardDetailRecyclerView.setAdapter(mWebCardListAdapter);
}

public void setEmptyListFragment(boolean isEmptyList) {
    isEmptyListFragment = isEmptyList;
}

}

最后这是我RecyclerView在片段中使用的适配器

public class WebCardListAdapter extends RecyclerView.Adapter<WebCardListAdapter.ViewHolder> {
private       Context                             mContext;
private       ArrayList<WebCardBaseResponseModel> mWebCardDetailList;
private boolean isFavorites;

public WebCardListAdapter(Context context, ArrayList<WebCardBaseResponseModel> webCardDetailList, boolean isFavorites) {
    mContext = context;
    mWebCardDetailList = webCardDetailList;
    this.isFavorites = isFavorites;
}

@NonNull
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_webcard_detail_layout, parent, false);
    return new ViewHolder(view);
}

@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
    setListItemView(holder, position);
    setListItemClickListener(holder);
}

@Override
public int getItemCount() {
    return mWebCardDetailList.size();
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public int getItemViewType(int position) {
    return position;
}

class ViewHolder extends RecyclerView.ViewHolder {
    private TextView     mCardNameTextView;
    private LinearLayout mWeCardLinearLayout;
    @BindView(R.id.tv_phone)
    TextView phone;

    ViewHolder(View itemView) {
        super(itemView);
        ButterKnife.bind(this, itemView);
        mCardNameTextView = (TextView) itemView.findViewById(R.id.webcard_name_textview);
        mWeCardLinearLayout = (LinearLayout) itemView.findViewById(R.id.wed_card_title_linear_layout);
    }
}

}

我希望ListView两个选项卡内部都是独立的。当我将元素添加到第二个选项卡RecyclerView时,这不应该反映在第一个选项卡RecyclerView中。

标签: androidandroid-recyclerviewandroid-viewpager

解决方案


基本区别

FragmentPagerAdapter

适用于有限(固定)数量的项目(片段)。为什么?因为它一旦创建就永远不会从 FragmentManager 中删除片段实例(除非 Activity 完成)。它仅将视图从当前不可见的片段中分离出来。onDestroyView() 将在您的 Fragment 无法访问时调用,稍后 onCreateView() 将在您返回此 Fragment 时调用。

FragmentStatePagerAdapter

FragmentStatePagerAdapter 更节省内存。一旦 Fragment 实例无法访问,它就会从 FragmentManager 中完全删除它们。已移除 Fragment 的状态存储在 FragmentStatePagerAdapter 中。一旦您返回到现有项目并恢复状态,就会重新创建 Fragment 实例。此适配器适用于计数未知的列表或项目变化很大的列表。

所以 FragmentPagerAdapter 会解决这个问题

我在视图寻呼机上调用 notifyDatasetChanged()。因此,每次片段内的回收器视图都会重新初始化。


推荐阅读