webentwicklung-frage-antwort-db.com.de

RecyclerView.Adapter.notifyItemChanged () übergibt niemals Nutzdaten an onBindViewHolder ()

Ich versuche, eine ViewHolder in einer RecyclerView zu aktualisieren, ohne die gesamte Sache neu zu binden. Laut den Dokumenten sollte ich dies durch Aufruf von RecyclerView.Adapter.notifyItemChanged(int position, Object payload) tun, wobei payload ein beliebiges Objekt ist, das an RecyclerView.Adapter.onBindViewHolder(VH holder, int position, List<Object> payloads) übergeben wird. Dort kann ich den ViewHolder aktualisieren.

Wenn ich dies versuche, erhält onBindViewHolder immer eine leere Liste. Zwischen diesen beiden Aufrufen wird die interne Liste der Nutzlasten gelöscht. Nach dem Setzen von Haltepunkten am Quellcode von RecyclerView geschieht dies aufgrund eines Relayouts, der schließlich RecyclerView.ViewHolder.clearPayload() aufruft.

Hat es noch jemandem geschafft, das zum Laufen zu bringen? Ist dies ein Fehler in der Support-Bibliothek oder habe ich etwas getan, um ein Relayout zwischen diesen beiden Funktionen auszulösen?

Hier ist der Stack-Trace für das Löschen der Nutzdaten:

"<1> [email protected]" prio=5 runnable
  Java.lang.Thread.State: RUNNABLE
      at Android.support.v7.widget.RecyclerView$ViewHolder.clearPayload(RecyclerView.Java:8524)
      at Android.support.v7.widget.RecyclerView$ViewHolder.resetInternal(RecyclerView.Java:8553)
      at Android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.Java:4544)
      at Android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.Java:4461)
      at Android.support.v7.widget.LayoutState.next(LayoutState.Java:86)
      at Android.support.v7.widget.StaggeredGridLayoutManager.fill(StaggeredGridLayoutManager.Java:1423)
      at Android.support.v7.widget.StaggeredGridLayoutManager.onLayoutChildren(StaggeredGridLayoutManager.Java:610)
      at Android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.Java:2847)
      at Android.support.v7.widget.RecyclerView.onLayout(RecyclerView.Java:3145)
      at Android.view.View.layout(View.Java:14289)
      at Android.view.ViewGroup.layout(ViewGroup.Java:4562)
      at Android.support.v4.widget.SwipeRefreshLayout.onLayout(SwipeRefreshLayout.Java:581)
      at Android.view.View.layout(View.Java:14289)
      at Android.view.ViewGroup.layout(ViewGroup.Java:4562)
      at Android.widget.FrameLayout.onLayout(FrameLayout.Java:448)
      at Android.view.View.layout(View.Java:14289)
      at Android.view.ViewGroup.layout(ViewGroup.Java:4562)
      at Android.widget.FrameLayout.onLayout(FrameLayout.Java:448)
      at Android.view.View.layout(View.Java:14289)
      at Android.view.ViewGroup.layout(ViewGroup.Java:4562)
      at Android.widget.FrameLayout.onLayout(FrameLayout.Java:448)
      at Android.view.View.layout(View.Java:14289)
      at Android.view.ViewGroup.layout(ViewGroup.Java:4562)
      at Android.widget.FrameLayout.onLayout(FrameLayout.Java:448)
      at Android.view.View.layout(View.Java:14289)
      at Android.view.ViewGroup.layout(ViewGroup.Java:4562)
      at Android.widget.LinearLayout.setChildFrame(LinearLayout.Java:1671)
      at Android.widget.LinearLayout.layoutVertical(LinearLayout.Java:1525)
      at Android.widget.LinearLayout.onLayout(LinearLayout.Java:1434)
      at Android.view.View.layout(View.Java:14289)
      at Android.view.ViewGroup.layout(ViewGroup.Java:4562)
      at Android.support.v4.widget.DrawerLayout.onLayout(DrawerLayout.Java:1043)
      at Android.view.View.layout(View.Java:14289)
      at Android.view.ViewGroup.layout(ViewGroup.Java:4562)
      at Android.widget.FrameLayout.onLayout(FrameLayout.Java:448)
      at Android.view.View.layout(View.Java:14289)
      at Android.view.ViewGroup.layout(ViewGroup.Java:4562)
      at Android.widget.LinearLayout.setChildFrame(LinearLayout.Java:1671)
      at Android.widget.LinearLayout.layoutVertical(LinearLayout.Java:1525)
      at Android.widget.LinearLayout.onLayout(LinearLayout.Java:1434)
      at Android.view.View.layout(View.Java:14289)
      at Android.view.ViewGroup.layout(ViewGroup.Java:4562)
      at Android.widget.FrameLayout.onLayout(FrameLayout.Java:448)
      at Android.view.View.layout(View.Java:14289)
      at Android.view.ViewGroup.layout(ViewGroup.Java:4562)
      at Android.widget.LinearLayout.setChildFrame(LinearLayout.Java:1671)
      at Android.widget.LinearLayout.layoutVertical(LinearLayout.Java:1525)
      at Android.widget.LinearLayout.onLayout(LinearLayout.Java:1434)
      at Android.view.View.layout(View.Java:14289)
      at Android.view.ViewGroup.layout(ViewGroup.Java:4562)
      at Android.widget.FrameLayout.onLayout(FrameLayout.Java:448)
      at Android.view.View.layout(View.Java:14289)
      at Android.view.ViewGroup.layout(ViewGroup.Java:4562)
      at Android.view.ViewRootImpl.performLayout(ViewRootImpl.Java:1976)
      at Android.view.ViewRootImpl.performTraversals(ViewRootImpl.Java:1730)
      at Android.view.ViewRootImpl.doTraversal(ViewRootImpl.Java:1004)
      at Android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.Java:5481)
      at Android.view.Choreographer$CallbackRecord.run(Choreographer.Java:749)
      at Android.view.Choreographer.doCallbacks(Choreographer.Java:562)
      at Android.view.Choreographer.doFrame(Choreographer.Java:532)
      at Android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.Java:735)
      at Android.os.Handler.handleCallback(Handler.Java:730)
      at Android.os.Handler.dispatchMessage(Handler.Java:92)
      at Android.os.Looper.loop(Looper.Java:137)
      at Android.app.ActivityThread.main(ActivityThread.Java:5103)
      at Java.lang.reflect.Method.invokeNative(Method.Java:-1)
      at Java.lang.reflect.Method.invoke(Method.Java:525)
      at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:737)
      at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:553)
      at dalvik.system.NativeStart.main(NativeStart.Java:-1)
23
philippe

RecyclerView standardmäßig erstellt eine weitere Kopie der ViewHolder, um die Ansichten ineinander einzublenden. Dies führt zu dem Problem, da die alte ViewHolder die Nutzlast erhält, die neue jedoch nicht. Sie müssen es daher ausdrücklich sagen, um das alte wiederzuverwenden:

DefaultItemAnimator animator = new DefaultItemAnimator() {
        @Override
        public boolean canReuseUpdatedViewHolder(RecyclerView.ViewHolder viewHolder) {
            return true;
        }
    };
mRecyclerView.setItemAnimator(animator);
29
Patricia Li

Wenn Sie den Elementanimator verwenden (standardmäßig aktiviert), ist die Nutzlast immer leer. Schauen Sie sich diese Antwort im Android-Ausgabe-Tracker an :

So gestaltet sich die Nutzlast. Es wird nur an on bind weitergegeben, "wenn wir an denselben Ansichtshalter binden". Dasselbe gilt für die Datenbindung. Wenn Sie nicht an denselben Ansichtsinhaber binden, können Sie die Bindung nicht inkrementell durchführen. Im Falle von Änderungsanimationen erstellt RV zwei Kopien der View, um das Überblenden zu überbrücken, sodass Sie in postLayout nicht an dieselbe VH gebunden sind.

In Kürze bieten wir eine API zum Ausführen von Änderungsanimationen innerhalb derselben ViewHolder.

Daher müssen wir, bis sie diese neue API freigeben, Folgendes verwenden:

mRecyclerView.setItemAnimator(null);

edit: .__ Siehe den @ blindOSX-Kommentar, wo er bemerkt hat, dass zur Aktivierung von Payloads nur Animationen von Elementänderungsereignissen deaktiviert werden können.

edit2: Sieht aus, als hätten sie dieses Verhalten ohne vorherige Benachrichtigung aktualisiert. Siehe aktualisierte @Patricia Li Antwort .

12
sosite

In einigen Fällen funktionierte es mit notifyItemRangeChanged(getItemRealCount(), 1).

1
joe

warum nicht einfach RecyclerView.Adapter.notifyItemChanged(int position) verwenden, scheint die Dokumentation etwas mehrdeutig zu sein 

  RecyclerView.Adapter.notifyItemChanged(int position,Object payload)

Der Kunde kann optional eine Nutzlast für eine teilweise Änderung übergeben. Diese Payloads werden zusammengeführt und können an die .__ des Adapters übergeben werden. onBindViewHolder (ViewHolder, int, List)

daher kann nicht garantiert werden, dass Sie die Liste in Ihrem onBindViewHolder erhalten 

0
harshitpthk