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);
}
}
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With