J'ai une RecyclerView
dans mon application, tout fonctionne bien. Je suis en train de faire défiler l'écran lorsque le dernier élément est visible. J'ajoute un élément supplémentaire au bas de la page et tout fonctionne correctement. Maintenant, quel est le problème, c’est que j’ai une Handler
qui s’exécute toutes les 5 secondes et vérifie s’il existe une mise à jour dans le service Web et s’il existe une mise à jour, je charge simplement les données au-dessus de la RecyclerView
cela fonctionne bien lorsque pas fait défiler la RecyclerView
mais quand je le fais défiler et que la Handler
est appelée (comme elle est appelée toutes les 5 secondes), puis lors de la mise à jour de la RecyclerView
en haut, l'application se bloque.
Fonction de mise à jour en haut:
public void addOnTop(ArrayList<ItemPOJO> topItemList) {
for (int i = topItemList.size() - 1; i >= 0; i--) {
itemList.add(0, topItemList.get(i));
}
notifyItemRangeInserted(0, topItemList.size());
notifyDataSetChanged();
}
C'est le journal des erreurs:
Java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder{419b8760 position=5 id=-1, oldPos=-1, pLpos:-1 no parent}
at Android.support.v7.widget.RecyclerView$Recycler.validateViewHolderForOffsetPosition(RecyclerView.Java:4214)
at Android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.Java:4345)
at Android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.Java:4326)
at Android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.Java:1955)
at Android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.Java:1364)
at Android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.Java:1327)
at Android.support.v7.widget.LinearLayoutManager.scrollBy(LinearLayoutManager.Java:1155)
at Android.support.v7.widget.LinearLayoutManager.scrollVerticallyBy(LinearLayoutManager.Java:1012)
at Android.support.v7.widget.RecyclerView.scrollByInternal(RecyclerView.Java:1363)
at Android.support.v7.widget.RecyclerView.onTouchEvent(RecyclerView.Java:2227)
at Android.view.View.dispatchTouchEvent(View.Java:7190)
at Android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.Java:2274)
at Android.view.ViewGroup.dispatchTouchEvent(ViewGroup.Java:2009)
at Android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.Java:2280)
at Android.view.ViewGroup.dispatchTouchEvent(ViewGroup.Java:2023)
at Android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.Java:2280)
at Android.view.ViewGroup.dispatchTouchEvent(ViewGroup.Java:2023)
at Android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.Java:2280)
at Android.view.ViewGroup.dispatchTouchEvent(ViewGroup.Java:2023)
at Android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.Java:2280)
at Android.view.ViewGroup.dispatchTouchEvent(ViewGroup.Java:2023)
at Android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.Java:2280)
at Android.view.ViewGroup.dispatchTouchEvent(ViewGroup.Java:2023)
at Android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.Java:2280)
at Android.view.ViewGroup.dispatchTouchEvent(ViewGroup.Java:2023)
at Android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.Java:2280)
at Android.view.ViewGroup.dispatchTouchEvent(ViewGroup.Java:2023)
at com.Android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.Java:1931)
at com.Android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.Java:1385)
at Android.app.Activity.dispatchTouchEvent(Activity.Java:2396)
at Android.support.v7.internal.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.Java:59)
at Android.support.v7.internal.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.Java:59)
at com.Android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.Java:1879)
at Android.view.View.dispatchPointerEvent(View.Java:7370)
at Android.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.Java:3182)
at Android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.Java:3127)
at Android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.Java:4164)
at Android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.Java:4143)
at Android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.Java:4235)
at Android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.Java:171)
at Android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native Method)
at Android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.Java:163)
at Android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.Java:4214)
at Android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run(ViewRootImpl.Java:4254)
at Android.view.Choreographer$CallbackRecord.run(Choreographer.Java:725)
at Android.view.Choreographer.doCallbacks(Choreographer.Java:555)
at Android.view.Choreographer.doFrame(Choreographer.Java:523)
at Android.view.Choreographer$FrameDisplayEventReceiver.run(Choreog
P.S .: com.Android.support:recyclerview-v7:22.2.1
est utilisé
Ce blocage peut être dû au fait que les méthodes setViewHolder
et onBind
sont appelées pendant la mise à jour de votre liste (utilisée par l'adaptateur), mais que notifyDataSetChanged()
n'a pas été appelé. Cela se produit généralement si vous faites défiler la liste ou naviguez pendant la mise à jour de la liste.
Solution: Conservez une liste séparée (tempList
) d'éléments ItemPOJO et ajoutez topData
à cette liste . Effacez ensuite la liste utilisée pour l'adaptateur, définissez sa liste avec tempList
et appelez notifyDataSetChanged()
.
C'est un bug de RV, voir la discussion ici .
Dans la plupart des cas, l'utilisation de notifyDataSetChanged()
évitera ce blocage, mais cela tuerait l'animation et les performances.
Essayez de désactiver recyclerview en rafraîchissant:
recyclerView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
Changez votre code comme ceci:
public void addOnTop(ArrayList<ItemPOJO> topItemList) {
Collections.reverse(topItemList);
itemList.addAll(0, topItemList);
notifyItemRangeInserted(0, topItemList.size());
}
c'est bizarre mais de cette façon j'ai résolu mon problème!
Essaye ça:
notifyItemRangeInserted(0, topItemList.size()-1);