I have a RecyclerView
which shows two kinds of View
s one represents an User publication and another that represents an Event publication. Both have elements in common, for example a TextView
that shows a time stamp. So I created a PublicationViewHolder
that takes this TextView
time stamp into a variable and load it. My issue is that the adapter, initially, load the right values, but when I scroll down, and scroll up again, the values in the positions are changed by values from another positions. Here is the code:
public class PublicationViewHolder extends RecyclerView.ViewHolder {
private TextView vTimeStamp;
public PublicationViewHolder(View itemView) {
super(itemView);
this.vTimeStamp = (TextView) itemView.findViewById(R.id.txt_view_publication_timestamp);
}
public void load(Publication publication, int i) {
load(publication);
try {
if (Publication.TYPE_USER_PUBLICATION == publication.getType()) {
load((UserPublication) publication);
} else if (Publication.TYPE_EVENT_PUBLICATION == publication.getType()) {
load((EventPublication) publication);
}
} catch (ClassCastException e) {
throw new RuntimeException("Publication type cast fail. See PublicationViewHolder.");
}
}
public void load(Publication publication) {
vTimeStamp.setText(DateFormatter.getTimeAgo(publication.getTimeStamp()));
}
public void load( UserPublication publication) {
//This method is override by UserPublicationViewHolder
};
public void load( EventPublication publication) {
//This method is override by EventPublicationViewHolder
};
}
Now I will make my UserPublicationViewHolder
for users publications only.
public class UserPublicationViewHolder extends PublicationViewHolder {
private ImageView vImageView, vLikeButton, vDislikeButton, vFavButton, vEditPost, vDeletePost;
private TextView vText, vUsername, vLikeCount, vDislikeCount, vFavCount;
private PostImagesLayout vImagesContainer;
private TagCloudLocationFriends tagsView;
public UserPublicationViewHolder(View itemView) {
super(itemView);
vImageView = (ImageView) itemView.findViewById(R.id.img_view_publication_user);
vText = (TextView) itemView.findViewById(R.id.txt_view_publication_text);
vLikeCount = (TextView) itemView.findViewById(R.id.txt_view_like_count);
vFavCount = (TextView) itemView.findViewById(R.id.txt_view_fav_count);
vDislikeCount = (TextView) itemView.findViewById(R.id.txt_view_dislike_count);
vUsername = (TextView) itemView.findViewById(R.id.txt_view_publication_user_name);
vLikeButton = (ImageView) itemView.findViewById(R.id.img_view_like);
vDislikeButton = (ImageView) itemView.findViewById(R.id.img_view_dislike);
vFavButton = (ImageView) itemView.findViewById(R.id.img_view_fav);
vImagesContainer = (PostImagesLayout) itemView.findViewById(R.id.container_post_images);
tagsView = (TagCloudLocationFriends) itemView.findViewById(R.id.location_friends_tag);
// edit - remove icons
vDeletePost = (ImageView) itemView.findViewById(R.id.img_view_delete_post);
vEditPost = (ImageView) itemView.findViewById(R.id.img_view_edit_post);
}
@Override
public void load(UserPublication publication) {
//Load the UserPublicationViewHolder specific views.
}
}
Now I will do the same but for the Event publications
public class EventPublicationViewHolder extends PublicationViewHolder {
private TextView vTextViewTitle;
private TextView vTextViewText;
public EventPublicationViewHolder(View itemView) {
super(itemView);
vTextViewTitle = (TextView) itemView.findViewById(R.id.txt_view_publication_event_title);
vTextViewText = (TextView) itemView.findViewById(R.id.txt_view_publication_event_text);
}
@Override
public void load(EventPublication publication) {
//Load the EventPublicationViewHolder specifics views
}
}
Now here is my RecyclerView adapter:
public class PublicationAdapter extends RecyclerView.Adapter<PublicationViewHolder> {
public static final int USER_PUBLICATION_TYPE = 1;
public static final int EVENT_PUBLICATION_TYPE = 2;
private List<Publication> publications = new ArrayList<Publication>();
public List<Publication> getPublications() {
return publications;
}
public void setPublications(List<Publication> publications) {
this.publications = publications;
}
@Override
public int getItemViewType(int position) {
if (publications.get(position) instanceof UserPublication) {
return USER_PUBLICATION_TYPE;
}
if (publications.get(position) instanceof EventPublication) {
return EVENT_PUBLICATION_TYPE;
}
throw new RuntimeException("Unknown view type in PublicationAdapter");
}
@Override
public PublicationViewHolder onCreateViewHolder(ViewGroup viewGroup, int type) {
View v;
switch (type) {
case USER_PUBLICATION_TYPE:
v = LayoutInflater.from(getActivity()).inflate(R.layout.view_holder_user_publication, viewGroup, false);
return new UserPublicationViewHolder(v);
case EVENT_PUBLICATION_TYPE:
v = LayoutInflater.from(getActivity()).inflate(R.layout.view_holder_event_publication, viewGroup, false);
return new EventPublicationViewHolder(v);
}
return null;
}
@Override
public void onBindViewHolder(PublicationViewHolder aPublicationHolder, int i) {
aPublicationHolder.load(publications.get(i), i);
}
@Override
public long getItemId(int position) {
//Here I tried returning only position or 0 without luck.
//The id is unique BTW
return publications.get(position).getId();
}
@Override
public int getItemCount() {
return publications.size();
}
}
I don't know what can be wrong, UserPublication and EventPublication both extends from Publication. I'm not doing some request or reloading the adapter. I only load the adapter once.
Update:
BTW I'm using this RecyclerView inside a Fragment which is loaded in a PageAdapter which is loaded in a ViewPager that is inside a Fragment, maybe is this the issue?
Update:
This is the other binding code.
This is the load method of the UserPublicationViewHolder
.
@Override
public void load(UserPublication publication) {
PicassoHelper.publicationUser(getActivity(), publication.getUser().getAvatarUrl(),
vImageView);
vText.setText(publication.getText());
vUsername.setText(publication.getUser().getName());
boolean hasLocation = false;
if (publication.getImages().length > 0) {
vImagesContainer.setImages(publication.getImages());
} else {
vImagesContainer.setVisibility(View.GONE);
}
tagsView.setTags(new ArrayList<MinikastTag>());
tagsView.drawTags();
if(publication.getLocation() != null || publication.getTaggedFriends().size() > 0){
if(publication.getLocation() != null){
hasLocation = true;
tagsView.add(new MinikastTag(1,"Post from ",1));
tagsView.add(new MinikastTag(2, publication.getLocation().getName(), 2));
}
if(publication.getTaggedFriends().size() > 0){
if(hasLocation)
tagsView.add(new MinikastTag(3," with ",1));
else
tagsView.add(new MinikastTag(3,"With ",1));
int i = 0;
for(User aUser: publication.getTaggedFriends()){
MinikastTag aTag;
if(i == publication.getTaggedFriends().size() - 1 ) {
aTag = new MinikastTag(4, aUser.getName(), 3);
aTag.setUserID(aUser.getId());
aTag.setUserName(aUser.getName());
tagsView.add(aTag);
} else {
aTag = new MinikastTag(4, aUser.getName() + ", ", 3);
aTag.setUserID(aUser.getId());
aTag.setUserName(aUser.getName());
tagsView.add(aTag);
}
i = i+1;
}
}
}
tagsView.drawTags();
// likes, dislikes, favs
if(publication.getLikesAmount() > 0)
vLikeCount.setText(String.valueOf(publication.getLikesAmount()));
if(publication.getDislikesAmount() > 0)
vDislikeCount.setText(String.valueOf(publication.getDislikesAmount()));
if(publication.getLovesAmount() > 0)
vFavCount.setText(String.valueOf(publication.getLovesAmount()));
// reset buttons
vFavButton.setPressed(false);
vDislikeButton.setPressed(false);
vLikeButton.setPressed(false);
if(publication.getRelationship().equals("LOVE"))
vFavButton.setPressed(true);
else if (publication.getRelationship().equals("LIKE"))
vLikeButton.setPressed(true);
else if (publication.getRelationship().equals("DISLIKE"))
vDislikeButton.setPressed(true);
// edit - remove icons
if(String.valueOf(publication.getUser().getId()).equals(StartupSharedPreferences.getProfileId())){
vEditPost.setVisibility(View.VISIBLE);
vDeletePost.setVisibility(View.VISIBLE);
}else{
vEditPost.setVisibility(View.INVISIBLE);
vDeletePost.setVisibility(View.INVISIBLE);
}
}
}
And this is the load method of the EventPublicationViewHolder:
@Override
public void load(EventPublication publication) {
vTimeStamp.setVisibility(View.GONE);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//GoTo.eventDetail(getActivity(), publication);
}
});
vTextViewTitle.setText(publication.getTitle());
vTextViewText.setText(publication.getText());
}
I commented some code just because I was testing, but as you can see, I only do setTexts and assing some images.
And this is how I set the adapter, LinearLayoutManager, etc. In the onViewCreated method of the fragment.
vRecyclerView = (FixedRecyclerView) view.findViewById(R.id.recycler_view_publications);
vSwipeRefresh = (SwipeRefreshLayout) view.findViewById(R.id.swipe_container);
mFeedCallback.onScrollReady(vRecyclerView);
mLayoutManager = buildLayoutManager();
vRecyclerView.setLayoutManager(mLayoutManager);
vRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));
mAdapter = new PublicationAdapter();
vSwipeRefresh.setOnRefreshListener(this);
vSwipeRefresh.setColorSchemeResources(R.color._SWIPER_COLOR_1, R.color._SWIPER_COLOR_2,
R.color._SWIPER_COLOR_3,