Comment la position d'un adaptateur RecyclerView est-elle liée à l'index de son ensemble de données?
Je pensais qu'ils étaient les mêmes, mais ils ne sont pas. Le code suivant donne un indexOutOfBounds exception lorsque j'essaie d'accéder à la "position" de l'index de mon dataset, dans ce cas une liste d'un modèle que j'ai créé appelé Tâche:
public class TaskAdapter extends RecyclerView.Adapter<TaskAdapter.TaskViewHolder> {
private List<Task> taskList;
private TaskAdapter thisAdapter = this;
//cache of views to reduce number of findViewById calls
public static class TaskViewHolder extends RecyclerView.ViewHolder {
protected TextView taskTV;
protected ImageView closeBtn;
public TaskViewHolder(View v) {
super(v);
taskTV = (TextView)v.findViewById(R.id.taskDesc);
closeBtn = (ImageView)v.findViewById(R.id.xImg);
}
}
public TaskAdapter(List<Task> tasks) {
if(tasks == null)
throw new IllegalArgumentException("tasks cannot be null");
taskList = tasks;
}
//onBindViewHolder binds a model to a viewholder
@Override
public void onBindViewHolder(TaskViewHolder taskViewHolder, int pos) {
final int position = pos;
Task currTask = taskList.get(pos);
taskViewHolder.taskTV.setText(currTask.getDescription());
**taskViewHolder.closeBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("TRACE", "Closing task at position " + position);
//delete from SQLite DB
Task taskToDel = taskList.get(position);
taskToDel.delete();
//updating UI
taskList.remove(position);
thisAdapter.notifyItemRemoved(position);
}
});**
}
@Override
public int getItemCount() {
//Log.d("TRACE", taskList.size() + " tasks in DB");
return taskList.size();
}
//inflates row to create a viewHolder
@Override
public TaskViewHolder onCreateViewHolder(ViewGroup parent, int pos) {
View itemView = LayoutInflater.from(parent.getContext()).
inflate(R.layout.list_item, parent, false);
Task currTask = taskList.get(pos);
//itemView.setBackgroundColor(Color.parseColor(currTask.getColor()));
return new TaskViewHolder(itemView);
}
}
La suppression de mon recyclerview donne des résultats inattendus, parfois. Parfois, l'élément de l'avant de celui cliqué est supprimé, d'autres fois un indexOutOfBounds exception se produit au "taskList.get(position)".
Lecture https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html et https://developer.android.com/training/material/lists-cards.html ne m'a pas donné plus d'informations sur les raisons de cette situation et comment le résoudre.
Il ressemble RecyclerView recycle les lignes, mais je ne m'attends pas à un indexoutofbounds exception à l'aide d'un plus petit sous-ensemble de numéros d'index de ma liste.
source d'informationauteur HukeLau_DABA
Vous devez vous connecter pour publier un commentaire.
RecyclerView ne pas relier de vues lors de leur position de changement (pour d'évidentes raisons de performances).
Par exemple, si votre jeu de données ressemble à ceci:
et vous ajouter un élément X via
pour obtenir
RecyclerView ne liera X et exécuter l'animation.
Il y a un
getPosition
méthode dans ViewHolder mais qui peut ne pas correspondre à l'adaptateur de position si vous l'appelez dans le milieu de l'animation.Si vous avez besoin de l'adaptateur position, votre option la plus sûre est de la position de la Carte.
mise à jour pour votre commentaire
Ajouter un champ de Tâche à l'ViewHolder.
Changement
onCreateViewHolder
comme suit pour éviter de créer un objet écouteur sur chaque rebind.donc dans votre méthode bind, vous ne
Comme yigit dit, RecyclerView fonctionne comme ça:
et vous ajouter un élément X via
vous obtenez
À l'aide de
holder.getAdapterPosition()
dans onClickListener() vous donnera le droit de l'élément à partir d'un jeu de données pour être enlevé, de ne pas "statique" position de la vue. Voici la doc à ce sujet onBindViewHolderPourquoi ne pas vous utilisez une interface publique pour le clic sur le bouton et le controle de l'action dans le MainActivity.
De votre carte d'ajouter:
et
plus à l'appel dans la ViewHolder classe
Dans votre MainActivity changer votre adaptateur pour gérer l'appel
Personnellement, je n'aime pas ce concept de RecyclerViews. Semble que ce n'était pas la pensée de tout.
Comme il a été dit lors de la suppression d'un élément du Recycleur vue vient se cache un élément. Mais en général, vous ne voulez pas quitter cet élément dans votre collection. Lors de la suppression d'un élément de la collection "elle passe ses éléments vers 0" alors que recyclerView conserve la même taille.
Si vous appelez
taskList.remove(position);
votre position doit être évalué de nouveau:Grâce à @yigit pour sa réponse, sa solution principalement travaillé, j'ai juste modifié un peu, de manière à éviter l'utilisation de vh.getTask() dont je n'étais pas sûr de savoir comment mettre en œuvre.
Avis au lieu d'obtenir la mise à jour de la position, vous pouvez appeler vh.getAdapterPosition(), qui est la ligne qui va vous donner la mise à jour de la position du dataset sous-jacent plutôt que le faux point de vue.
Ce travail est pour moi comme de maintenant, si quelqu'un sait un inconvénient à l'utilisation de cette s'il vous plaît laissez-moi savoir. Espérons que cela aide quelqu'un.