web-dev-qa-db-fra.com

RecyclerView se bloque lors de la mise à jour par dessus

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é

10
Vishwajit Palankar

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().

6
Sid

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.

3
Piasy

Essayez de désactiver recyclerview en rafraîchissant:

recyclerView.setOnTouchListener(new View.OnTouchListener() {
      @Override
      public boolean onTouch(View v, MotionEvent event) {
          return true;
      }
  });
1
Rishabh Srivastava

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!

1
MaryPeak

Essaye ça:

 notifyItemRangeInserted(0, topItemList.size()-1);
0
damn