RecyclerView的项内容混乱了

3
我有一个包含有交互内容项的RecyclerView。每个项都包含一个TextView,该TextView每5秒更新一次,但是当RecyclerView中有5个以上的项时,数据会混乱。
例如:
正确情况: |1 - 100| |2 - 283| |3 - 382|
混乱情况: |2 - 283| |1 - 100| |3 - 382|
就像这样,它只是变得混乱了。
当我调用adapter.notifyDataSetChanged()时就会发生这种情况。
我的适配器: 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);
    }
}

}


请发布您的适配器类。 - Jeffalee
你已经成功修复它了吗?当我更改 Recycler-View 项内的文本视图的可见性并调用 notify-data-set-changed 时,我遇到了相同的问题。这太奇怪了 :-\ - t3chb0t
2个回答

2
你正在onBindViewHolder中进行异步调用,因此当异步任务的响应返回时,它会从public void onBindViewHolder(final FavoritesViewHolder holder, final int position)中读取错误的位置,因为此时onBindViewHolder返回的位置已经发生了改变。
你可以将位置作为参数传递到async task中,并在async task的结果中传递相同的位置。这样,对于位置p(例如),调用将应用于p
除此之外,还要尝试在RecyclerViewHolder上使用getAdapterPosition而不是getPosition(已弃用并且容易引起混淆)。

还是不行,我会录制一个视频给你看看它的样子。 - Bjarn Bronsveld
这里是视频链接,可以看到发生了什么:https://youtu.be/9KU2iKtMPCE 我会尽快更新代码。 - Bjarn Bronsveld
原因就是在我的答案中提供的那个。当异步任务返回时,position已经被改变了。 - Rohit Arya

0

你能检查一下是否在编辑传递给适配器构造函数的初始列表的顺序/排序吗?

 List<Favorites> channels = getChannels();
 adapter = new FavoritesAdapter(context, channels);
 recyclerView.setAdapter(adapter)
 //     edit or sort *channels*
 adapter.notifyDataSetChanged();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接