Ich habe eine RecyclerView
in meiner App. Alles funktioniert gut. Ich bin beim Scrollen, wenn das letzte Element sichtbar ist. Ich füge ein paar weitere Elemente an der Unterseite hinzu und es funktioniert einwandfrei. Nun, das Problem ist, dass ich eine Handler
habe, die alle 5 Sekunden ausgeführt wird, und überprüfen, ob es ein Update im Web-Service gibt. Wenn es ein Update gibt, lade ich einfach die Daten oben in die RecyclerView
ollte nicht die RecyclerView
rollen, aber wenn ich sie scrolle und die Handler
aufgerufen wird (wie sie alle 5 Sekunden aufgerufen wird), stürzt die App beim Aktualisieren der RecyclerView
oben ab.
Aktualisierungsfunktion oben:
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();
}
Dies ist das Fehlerprotokoll:
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
wird verwendet
Dieser Absturz kann durch die Tatsache verursacht werden, dass die Methoden setViewHolder
und onBind
aufgerufen werden, während Ihre vom Adapter verwendete Liste aktualisiert wird, notifyDataSetChanged()
jedoch nicht aufgerufen wurde. Dies geschieht normalerweise, wenn Sie durch die Liste blättern oder fliehen, während die Liste aktualisiert wird.
Lösung: Eine separate Liste (tempList
) von ItemPOJOs pflegen und die topData
in dieser Liste anhängen. Anschließend die Liste für den Adapter löschen, die Liste des Adapters mit der tempList
setzen und aufrufen notifyDataSetChanged()
.
Es ist ein Fehler im Wohnmobil, siehe die Diskussion hier .
In den meisten Fällen kann mit notifyDataSetChanged()
dieser Absturz vermieden werden, Animation und Performance werden jedoch abgebrochen.
Deaktivieren Sie die Recycler-Funktion während der Aktualisierung:
recyclerView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
Ändern Sie Ihren Code folgendermaßen:
public void addOnTop(ArrayList<ItemPOJO> topItemList) {
Collections.reverse(topItemList);
itemList.addAll(0, topItemList);
notifyItemRangeInserted(0, topItemList.size());
}
es ist komisch, aber auf diese Weise habe ich mein Problem gelöst!
Versuche dies:
notifyItemRangeInserted(0, topItemList.size()-1);