android - RecyclerView overdraw 项目

标签 android android-recyclerview

我在所有 RecyclerView 上都遇到了一个很奇怪的问题在我的申请中。这不是我第一次使用 RecyclerView但这是第一次发生。我认为最好的解释方式是用照片:

列表不断更新,因此经常调用通知方法。代码有点太复杂,无法发布,但我确信一切都是从 UI 线程调用的。

此处要求的是代码和布局。

代码:

public class PlayersAdapter extends RecyclerView.Adapter<PlayersAdapter.ViewHolder> {
    private final List<GameInfo.Player> players;
    private final LayoutInflater inflater;

    public PlayersAdapter(Context context, List<GameInfo.Player> players) {
        this.inflater = LayoutInflater.from(context);
        this.players = players;
        setHasStableIds(true);
    }

    @Override
    public long getItemId(int position) {
        return players.get(position).name.hashCode();
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new ViewHolder(parent);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        GameInfo.Player player = players.get(position);
        holder.name.setText(player.name);
        holder.update(player);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position, List<Object> payloads) {
        if (payloads.isEmpty()) {
            onBindViewHolder(holder, position);
        } else {
            holder.update((GameInfo.Player) payloads.get(0));
        }
    }

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

    public void notifyItemChanged(GameInfo.Player player) {
        int pos = players.indexOf(player);
        if (pos != -1) {
            players.set(pos, player);
            notifyItemChanged(pos, player);
        }
    }

    public void notifyDataSetChanged(List<GameInfo.Player> players) {
        this.players.clear();
        this.players.addAll(players);
        notifyDataSetChanged();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        final TextView name;
        final SuperTextView score;
        final ImageView status;

        ViewHolder(ViewGroup parent) {
            super(inflater.inflate(R.layout.player_item, parent, false));
            setIsRecyclable(false);

            name = itemView.findViewById(R.id.playerItem_name);
            score = itemView.findViewById(R.id.playerItem_score);
            status = itemView.findViewById(R.id.playerItem_status);
        }

        void update(GameInfo.Player player) {
            score.setHtml(R.string.score, player.score);

            switch (player.status) {
                case HOST:
                    status.setImageResource(R.drawable.ic_person_black_48dp);
                    break;
                case IDLE:
                    status.setImageResource(R.drawable.ic_access_time_black_48dp);
                    break;
                case JUDGING:
                case JUDGE:
                    status.setImageResource(R.drawable.ic_gavel_black_48dp);
                    break;
                case PLAYING:
                    status.setImageResource(R.drawable.ic_hourglass_empty_black_48dp);
                    break;
                case WINNER:
                    status.setImageResource(R.drawable.ic_star_black_48dp);
                    break;
                case SPECTATOR:
                    status.setImageResource(R.drawable.ic_remove_red_eye_black_48dp);
                    break;
            }
        }
    }
}

GameInfo.Player类:

public static class Player {
        public final String name;
        public final int score;
        public final PlayerStatus status;

        public Player(JSONObject obj) throws JSONException {
            name = obj.getString("N");
            score = obj.getInt("sc");
            status = PlayerStatus.parse(obj.getString("st"));
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Player player = (Player) o;
            return name.equals(player.name);
        }
    }

自定义项目布局(R.layout.player_item):

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:orientation="horizontal"
    android:padding="4dp">

    <ImageView
        android:id="@+id/playerItem_status"
        android:layout_width="32dp"
        android:layout_height="32dp"
        android:alpha="0.54"
        android:padding="4dp"
        android:scaleType="fitCenter" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:paddingStart="8dp">

        <TextView
            android:id="@+id/playerItem_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:lines="1"
            android:textColor="@android:color/primary_text_light"
            android:textSize="14sp" />

        <com.gianlu.commonutils.SuperTextView
            android:id="@+id/playerItem_score"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>
</LinearLayout>

编辑: 删除 onBindViewHolder(ViewHolder holder, int position, List<Object> payloads)方法仅在我使用 notifyItemChanged(pos, player) 时才解决问题,问题仍然存在 notifyItemChanged(pos) .很高兴知道为什么会这样。

最佳答案

我已经通过删除 onBindViewHolder(ViewHolder holder, int position, List<Object> payloads) 解决了这个问题方法,使用 notifyItemChanged(pos)而不是 notifyItemChanged(pos, player)并设置 ViewHolder可回收 setIsRecyclable(true) .感谢@RahulKumar 的建议。

关于android - RecyclerView overdraw 项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47053131/

相关文章:

android - 在整个 Activity 中重复使用 String 或 Int?

android - 通过 HCE 付款

java - 自定义 RecyclerAdapter 和 startActivityForResult

java - 如何在顶部显示特定的回收者 View 项目?

android - Getview在android中被多次调用

android - 为整个 Android 应用程序添加页脚

java - 如何设置卡片 View 的id?

android - RecyclerView 错误?

Java:读取文件,第一行丢失

android - 在 RecyclerView 的 ViewHolder 上不显示 getSupportFragmentManager