Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RecyclerView item content gets mixed up

I've got a RecyclerView containing items with interactive content. Every item contains a textview that's being updated every 5 seconds, but when there are more than 5 items in the RecyclerView, the data gets mixed up.

By example:

Correct: | 1 - 100 |

| 2 - 283 |

| 3 - 382 |

When it gets mixed up:

| 2 - 283 |

| 1 - 100 |

| 3 - 382 |

It's kinda like that, it just gets mixed up.

This happens when I call de adapter.notifyDataSetChanged();

My Adapter:

public class FavoritesAdapter extends RecyclerView.Adapter {

private List<Favorites> channels;
private Context context;

public FavoritesAdapter(Context context, List<Favorites> channels) {
    this.context = context;
    this.channels = channels;
}

@Override
public FavoritesViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
    View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.favoriteitem_layout, viewGroup, false);
    FavoritesViewHolder pvh = new FavoritesViewHolder(v);
    return pvh;
}

@Override
public void onBindViewHolder(final FavoritesViewHolder holder, final int position) {
    final DBHelper dbHelper = new DBHelper(context);
    if (Data.isConnected(context)) {
        Scheduler.getInstance().doAsync(new Scheduler.Task<Object, Channel>() {
            @Override
            public Channel run(Object... params) {
                return Methods.getData(channels.get(position).getChannelId(), channels.get(position).getChannelName(), true, context);
            }
        }, new Scheduler.Executable<Channel>() {
            @Override
            public void execute(Channel result) {

                if(result.getId() != "") {
                    if(!result.channelSubs.equalsIgnoreCase("-500_RTSS_ERROR")) {
                        holder.channelSubsView.setText(result.getSubs());
                        holder.channelTitleSubsView.setText(String.valueOf(channels.get(position).getChannelName()) + "'s Suscribers");
                        channels.get(position).setChannelSubs(result.getSubs());
                        dbHelper.updateFavorites(channels.get(position));
                    }
                    else {
                        holder.channelSubsView.setText(channels.get(position).getChannelSubs());
                        holder.channelTitleSubsView.setText(String.valueOf(channels.get(position).getChannelName()) + "'s Suscribers (Cached)");
                    }
                }
                else {
                    holder.channelSubsView.setText(channels.get(position).getChannelSubs());
                    holder.channelTitleSubsView.setText(String.valueOf(channels.get(position).getChannelName()) + "'s Suscribers (Cached)");
                }
            }
        });
    }
    else {
        holder.channelSubsView.setText(channels.get(position).getChannelSubs());
        holder.channelTitleSubsView.setText(String.valueOf(channels.get(position).getChannelName()) + "'s Suscribers (Cached)");
    }

    Picasso.with(context).load(channels.get(position).getChannelAvatar())
            .error(R.drawable.youtube_default_avatar)
            .placeholder(R.drawable.youtube_default_avatar)
            .into(holder.channelAvatarView);

    holder.channelCardView.setOnClickListener(clickListener);
    holder.channelCardView.setTag(holder);
}

View.OnClickListener clickListener = new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        FavoritesViewHolder holder = (FavoritesViewHolder) view.getTag();
        int position = holder.getPosition();

        Favorites channel = channels.get(position);
        if(Data.isConnected(context)) {
            Methods.getYouTubeData(channel.getChannelId(), channel.getChannelName(), channel.getChannelAvatar(), context);
        }
        else {
            Toast.makeText(context, R.string.error_connection_no_internet, Toast.LENGTH_LONG).show();
        }
    }
};

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

@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
    super.onAttachedToRecyclerView(recyclerView);
}

public static class FavoritesViewHolder extends RecyclerView.ViewHolder {
    CardView channelCardView;
    TextView channelSubsView;
    TextView channelTitleSubsView;
    ImageView channelAvatarView;

    FavoritesViewHolder(View itemView) {
        super(itemView);
        channelCardView = (CardView) itemView.findViewById(R.id.channelCardView);
        channelSubsView = (TextView) itemView.findViewById(R.id.subsAmount);
        channelTitleSubsView = (TextView) itemView.findViewById(R.id.subsText);
        channelAvatarView = (ImageView) itemView.findViewById(R.id.channelAvatarView);
    }
}

}

like image 330
Bjarn Bronsveld Avatar asked Dec 12 '25 09:12

Bjarn Bronsveld


1 Answers

You are making an asynchronous call in onBindViewHolder so when the response of the async tasks comes, it reads wrong position from public void onBindViewHolder(final FavoritesViewHolder holder, final int position) because by that time position returned by onBindViewHolder has changed.

What you can do is, pass the position into async task as a parameter and deliver the same position in the result of the async task. That way call made for position p (say) will be applied to p.

Along with that, also try to use getAdapterPosition instead of getPosition (deprecated and creates confusion) on RecyclerViewHolder.

like image 148
Rohit Arya Avatar answered Dec 15 '25 14:12

Rohit Arya



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!