У меня есть RecyclerView
, который показывает два вида View
, один представляет публикацию пользователя, а другой - публикацию события. Оба имеют общие элементы, например a TextView
, который показывает отметку времени. Поэтому я создал PublicationViewHolder
, который принимает эту метку времени TextView
в переменную и загружает ее. Моя проблема в том, что адаптер сначала загружает правильные значения, но когда я прокручиваю вниз и снова прокручиваю, значения в позициях меняются значениями из других позиций. Вот код:
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
};
}
Теперь я сделаю только мои публикации UserPublicationViewHolder
.
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.
}
}
Теперь я сделаю то же самое, но для публикаций Event
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
}
}
Теперь вот мой адаптер RecyclerView:
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();
}
}
Я не знаю, что может быть неправильным, UserPublication и EventPublication простираются от публикации. Я не делаю запрос или перезагружаю адаптер. Я загружаю адаптер только один раз.
Update:
BTW Я использую этот RecyclerView внутри фрагмента, который загружается в PageAdapter, который загружается в ViewPager, который находится внутри фрагмента, может быть, это проблема?
Update: Это другой код привязки.
Это метод загрузки 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);
}
}
}
И это метод загрузки 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());
}
Я прокомментировал некоторый код только потому, что тестировал, но, как вы можете видеть, я только делаю setTexts и выдаю некоторые изображения.
И вот как я устанавливаю адаптер, LinearLayoutManager и т.д. В методе onViewCreated фрагмента.
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, R.color._SWIPER_COLOR_4);
vRecyclerView.setAdapter(mAdapter);
BTW Адаптер загружается с набором данных в пользовательском методе, который у меня есть, называется onHttpClientReady, но это, похоже, не проблема.
Вот несколько скриншотов:
В начало списка, когда я впервые вхожу в приложение:
Тогда, когда я вернусь:
Кстати, не нравятся и любимые кнопки, если кто-то нажал их более одного раза, отобразит числовое значение, эти значения также будут потеряны, если они есть.
UPDATE: Теперь я знаю, что это было не потому, что вложенные фрагменты. Я изменил свой код таким образом, что теперь каждый фрагмент вкладки находится в PageStateAdapter, который находится внутри ViewPager, который находится внутри Activity. Но проблема все еще существует.
UPDATE: Я обнаружил, что метод getItemId никогда не выполняется, IDK почему еще.