J'essaye de mettre à jour les éléments d'un recycleview en utilisant notifyDataSetChanged ().
C'est ma méthode onBindViewHolder () dans l'adaptateur de recycleview.
@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
//checkbox view listener
viewHolder.getCheckbox().setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
//update list items
notifyDataSetChanged();
}
});
}
Ce que je veux faire, c'est mettre à jour les éléments de la liste, après avoir coché une case. J'obtiens cependant une exception illégale:"Cannot call this method while RecyclerView is computing a layout or scrolling"
java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling
at android.support.v7.widget.RecyclerView.assertNotInLayoutOrScroll(RecyclerView.java:1462)
at android.support.v7.widget.RecyclerView$RecyclerViewDataObserver.onChanged(RecyclerView.java:2982)
at android.support.v7.widget.RecyclerView$AdapterDataObservable.notifyChanged(RecyclerView.java:7493)
at android.support.v7.widget.RecyclerView$Adapter.notifyDataSetChanged(RecyclerView.java:4338)
at com.app.myapp.screens.RecycleAdapter.onRowSelect(RecycleAdapter.java:111)
J'ai également utilisé notifyItemChanged (), même exception. Un moyen secret de mettre à jour pour informer l'adaptateur que quelque chose a changé?
android
android-recyclerview
Arthur
la source
la source
Réponses:
Vous devez déplacer la méthode 'setOnCheckedChangeListener ()' vers ViewHolder qui est la classe interne de votre adaptateur.
onBindViewHolder()
n'est pas une méthode qui s'initialiseViewHolder
. Cette méthode est une étape d'actualisation de chaque article recycleur. Lorsque vous appeleznotifyDataSetChanged()
,onBindViewHolder()
sera appelé le nombre de fois de chaque élément.Donc, si vous
notifyDataSetChanged()
insérezonCheckChanged()
et initialisez checkBoxonBindViewHolder()
, vous obtiendrez IllegalStateException en raison de l'appel de méthode circulaire.cliquez sur la case à cocher -> onCheckedChanged () -> notifyDataSetChanged () -> onBindViewHolder () -> cocher la case -> onChecked ...
Simplement, vous pouvez résoudre ce problème en mettant un indicateur dans l'adaptateur.
essaye ça,
la source
AdapterViewObserver
tempsonBindViewHolder()
en cours.Vous pouvez simplement réinitialiser l'écouteur précédent avant d'apporter des modifications et vous n'obtiendrez pas cette exception.
la source
L'utilisation d'un
Handler
pour ajouter des éléments et appeler ànotify...()
partir de cela aHandler
résolu le problème pour moi.la source
Je ne sais pas bien, mais j'ai aussi eu le même problème. J'ai résolu ce problème en utilisant
onClickListner
surcheckbox
Essayez ceci, cela peut vous aider!
la source
la source
Lorsque vous avez l'erreur de message:
Simple, faites simplement ce qui cause l'exception dans:
la source
Trouvé une solution simple -
Ici, nous créons un exécutable à notifyItemChanged pour une position lorsque recyclerview est prêt à le gérer.
la source
votre élément CheckBox est en train de changer drawable lorsque vous appelez,
notifyDataSetChanged();
donc cette exception se produit. Essayez d'appelernotifyDataSetChanged();
en post de votre vue. Par exemple:la source
Au début, je pensais que la réponse de Moonsoo (la réponse acceptée) ne fonctionnerait pas pour moi car je ne peux pas initialiser mon
setOnCheckedChangeListener()
dans le constructeur ViewHolder car je dois le lier à chaque fois pour qu'il obtienne une variable de position mise à jour. Mais il m'a fallu beaucoup de temps pour réaliser ce qu'il disait.Voici un exemple de "l'appel de méthode circulaire" dont il parle:
Le seul problème avec cela, c'est que lorsque nous avons besoin d'initialiser le commutateur pour qu'il soit activé ou désactivé (à partir de l'état sauvegardé passé, par exemple), il appelle l'auditeur qui pourrait appeler
nofityItemRangeChanged
qui appelle àonBindViewHolder
nouveau. Vous ne pouvez pas appeleronBindViewHolder
lorsque vous êtes déjà dansonBindViewHolder
], car vous ne pouvez pasnotifyItemRangeChanged
si vous êtes déjà en train de signaler que la gamme d'articles a changé. Mais je n'avais besoin que de mettre à jour l'interface utilisateur pour l'afficher ou la désactiver, ne voulant en fait rien déclencher.Voici la solution que j'ai apprise de la réponse de JoniDS qui empêchera la boucle infinie. Tant que nous définissons l'auditeur sur "null" avant de définir Checked, il mettra à jour l'interface utilisateur sans déclencher l'auditeur, évitant ainsi la boucle infinie. Ensuite, nous pouvons définir l'auditeur après.
Code de JoniDS:
Solution complète à mon exemple:
la source
Pourquoi ne pas vérifier l'
RecyclerView.isComputingLayout()
état comme suit?la source
Alors que l'élément est lié par le gestionnaire de mise en page, il est très probable que vous définissiez l'état coché de votre case à cocher, ce qui déclenche le rappel.
Bien sûr, c'est une supposition car vous n'avez pas publié la trace complète de la pile.
Vous ne pouvez pas modifier le contenu de l'adaptateur pendant que RV recalcule la disposition. Vous pouvez l'éviter en n'appelant pas notifyDataSetChanged si l'état vérifié de l'élément est égal à la valeur envoyée dans le rappel (ce qui sera le cas si l'appel
checkbox.setChecked
déclenche le rappel).la source
Utilisez onClickListner sur la case à cocher au lieu de OnCheckedChangeListener, cela résoudra le problème
la source
Avant de
notifyDataSetChanged()
simplement vérifier cela avec cette méthode:recyclerView.IsComputingLayout()
la source
Utilisation simple Post:
la source
J'ai rencontré ce problème exact! Après que la réponse de Moonsoo n'ait pas vraiment fait flotter mon bateau, j'ai un peu dérangé et j'ai trouvé une solution qui a fonctionné pour moi.
Tout d'abord, voici une partie de mon code:
Vous remarquerez que je notifie spécifiquement à l'adaptateur la position que je change, au lieu de l'ensemble de données comme vous le faites. Cela étant dit, bien que je ne puisse pas garantir que cela fonctionnera pour vous, j'ai résolu le problème en enveloppant mon
notifyItemChanged()
appel dans un bloc try / catch. Cela a simplement attrapé l'exception, mais a quand même permis à mon adaptateur d'enregistrer le changement d'état et de mettre à jour l'affichage!J'espère que cela aide quelqu'un!
EDIT: J'admets que ce n'est probablement pas la manière appropriée / mature de gérer le problème, mais comme cela ne semble pas causer de problèmes en laissant l'exception non gérée, j'ai pensé partager au cas où ce serait bien assez pour quelqu'un d'autre.
la source
Cela se produit parce que vous définissez probablement l '«écouteur» avant de configurer la valeur de cette ligne, ce qui fait que l'écouteur est déclenché lorsque vous «configurez la valeur» pour la case à cocher.
Ce que vous devez faire est:
la source
la source
utilisez simplement la
isPressed()
méthode deCompoundButton
paronCheckedChanged(CompoundButton compoundButton, boolean isChecked)
exemple
la source
J'ai eu le même problème en utilisant la case à cocher et le RadioButton. Remplacer
notifyDataSetChanged()
parnotifyItemChanged(position)
travaillé. J'ai ajouté un champ booléenisChecked
au modèle de données. Ensuite, j'ai mis à jour la valeur booléenne et dansonCheckedChangedListener
, j'ai appelénotifyItemChanged(adapterPosition)
. Ce n'est peut-être pas le meilleur moyen, mais cela a fonctionné pour moi. La valeur booléenne est utilisée pour vérifier si l'élément est vérifié.la source
la plupart du temps, cela se produit parce que notifydatasetchanged appelle l' événement onCheckedchanged de la case à cocher et dans cet événement encore il y a notifydatasetchanged .
pour le résoudre, vous pouvez simplement vérifier que la case est cochée par programme ou que l'utilisateur l'a pressée. il y a la méthode IsPressed pour elle.
alors enveloppez tout le code listner dans la méthode isPressed. et c'est fait.
la source
J'ai souffert de ce problème pendant des heures et c'est ainsi que vous pouvez le résoudre. Mais avant de commencer, il y a certaines conditions à cette solution.
CLASSE DE MODÈLE
CHECKBOX dans ADAPTER CLASS
CONSTRUCTEUR DE CLASSE D'ADAPTATEUR ET LISTE DES MODÈLES
ONBINDVIEW [Veuillez utiliser onclick au lieu de onCheckChange]
}
la source
Pour moi, un problème est survenu lorsque j'ai quitté EditText par Terminé, Retour ou touche d'entrée extérieure. Cela entraîne la mise à jour du modèle avec le texte d'entrée, puis l'actualisation de la vue du recycleur via l'observation des données en direct.
Le problème était que le curseur / focus reste dans EditText.
Lorsque j'ai supprimé le focus en utilisant:
Notifier que la méthode d'affichage de l'outil de recyclage des données a changé a cessé de générer cette erreur.
Je pense que c'est l'une des raisons / solutions possibles à ce problème. Il est possible que cette exception puisse être corrigée d'une autre manière car elle peut être causée par une raison totalement différente.
la source