Reputation: 61
I have a Viewpager
with two tabs inside. The tabs are Cards and Favorite cards. I am using same fragment inside both tabs. The fragment contains a RecyclerView
which I update dynamically. I add elements to both tabs one by one. I first completely add elements to first tab(Cards tab), after finishing that I add elements to second tab(Favorite card tab). My problem is when I add elements to the second tab, my RecyclerView
inside first tab also get updated. Now the elements in first tab RecyclerView
is the sum of existing elements plus the elements I add in the second tab. I set two different ArrayList in both the ViewPager
tab. But when getItemCount()
called in first tab RecyclerView
, the ArrayList has the element that I added in the second tab.
I am using the same fragment with a RecyclerView
in both tabs. When I want to update a single tab, I call notifyDatasetChanged()
on the ViewPager
. So each time RecyclerView
inside the fragment is reinitialized.
This is my Viewpager adapter
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);
}
}
}
This is my Card fragment
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;
}
}
Finally this is my RecyclerView
adapter I use inside the fragment
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);
}
}
}
I want the ListView
inside both tabs to be independent. When I add elements to the second tab RecyclerView
, that should not reflect in the first tab RecyclerView
.
Upvotes: 1
Views: 1538
Reputation: 61
Thanks for the answers, anyway this issue has got nothing to do with Recyclerview
or Viewpager
, it happened because of my misunderstanding on the variable reference. I change the ArrayList
somewhere else inside the activity. That affects the list in recyclerview
.
Upvotes: 0
Reputation: 126
Remove the override function "getItemPosition" from vew pager adapter class. Hope it will help.
Upvotes: 0
Reputation: 1275
The Basic difference
FragmentPagerAdapter
Good for a limited (fixed) number of items (Fragments). Why? Because it never removes a fragment instance from FragmentManager once it’s created (unless that Activity is finished). It only detaches the Views from Fragments which are currently not visible. onDestroyView() will be called on your Fragment once it’s out of reach and later onCreateView() will be called once you go back to this Fragment.
FragmentStatePagerAdapter
A FragmentStatePagerAdapter is more memory savvy. It completely removes Fragment instances from the FragmentManager once they are out of reach. The state of the removed Fragments is stored inside the FragmentStatePagerAdapter. The Fragment instance is recreated once you return back to an existing item and the state is restored. This adapter is suitable for lists with an unknown count or for lists where the items change a lot.
So FragmentPagerAdapter will solve this
I call notifyDatasetChanged() on the view pager. So each time recycler view inside the fragment is reinitialised.
Upvotes: 1