Reputation: 1029
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);
}
}
}
Upvotes: 3
Views: 1930
Reputation: 6791
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.
Upvotes: 2
Reputation: 101
Can you check if you are editing the order/ sorting of the initial list passed to the constructor of the adapter.
List<Favorites> channels = getChannels();
adapter = new FavoritesAdapter(context, channels);
recyclerView.setAdapter(adapter)
// edit or sort *channels*
adapter.notifyDataSetChanged();
Upvotes: 0