私のアプリケーションでは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>
EDIT: はonBindViewHolder(ViewHolder holder, int position, List<Object> payloads)
削除メソッドはnotifyItemChanged(pos, player)
を使用した場合にのみ問題を解決し、問題はnotifyItemChanged(pos)
のままです。なぜそれが起こるか知っていいだろう。
あなたは 'RecyclerView'のコードを投稿できますか? –
は、RecyclerViewアイテムからあなたのカスタムレイアウトを共有します。 –
@NileshRathod質問 – Gianlu