2015-05-06 3 views
10

Ich verwende RecyclerView als eine Liste, um Songs anzuzeigen, die heruntergeladen werden können. Jeder Artikel hat ProgressBar in seinem View. Wenn der Download beginnt, dann verwende ich ein Handler jedes Element zu benachrichtigen, die ProgressBar zu aktualisieren, den Song Download-Fortschritt zu zeigen.RecyclerView wird abgestürzt [IllegalArgumentException], wenn notifyItemChanged von Handler mit Runnable

Q1. Ist dies ein richtiger Weg dies zu tun oder gibt es einen anderen Weg dies besser zu tun?

Q2. RecyclerView wird abgestürzt, wenn wir adapter.notifyItemChanged(position); verwenden, um den Inhalt eines einzelnen Elements zu aktualisieren. Es wird von Handler mit Runnable aufgerufen. Aber das Protokoll zeigt keine Spuren für meinen Code. Warum?

Unten ist das Protokoll für dieses Problem:

05-06 19:09:45.804: E/AndroidRuntime(32115): FATAL EXCEPTION: main 
05-06 19:09:45.804: E/AndroidRuntime(32115): java.lang.IllegalArgumentException: Tmp detached view should be removed from RecyclerView before it can be recycled: ViewHolder{41b7bec0 position=6 id=-1, oldPos=-1, pLpos:-1 update changed tmpDetachedundefined adapter position no parent} 
05-06 19:09:45.804: E/AndroidRuntime(32115): at android.support.v7.widget.RecyclerView$Recycler.recycleViewHolderInternal(RecyclerView.java:3861) 
05-06 19:09:45.804: E/AndroidRuntime(32115): at android.support.v7.widget.RecyclerView.removeAnimatingView(RecyclerView.java:779) 
05-06 19:09:45.804: E/AndroidRuntime(32115): at android.support.v7.widget.RecyclerView.access$5300(RecyclerView.java:127) 
05-06 19:09:45.804: E/AndroidRuntime(32115): at android.support.v7.widget.RecyclerView$ItemAnimatorRestoreListener.onAddFinished(RecyclerView.java:8228) 
05-06 19:09:45.804: E/AndroidRuntime(32115): at android.support.v7.widget.RecyclerView$ItemAnimator.dispatchAddFinished(RecyclerView.java:8573) 
05-06 19:09:45.804: E/AndroidRuntime(32115): at android.support.v7.widget.DefaultItemAnimator$5.onAnimationEnd(DefaultItemAnimator.java:239) 
05-06 19:09:45.804: E/AndroidRuntime(32115): at android.support.v4.view.ViewPropertyAnimatorCompatJB$1.onAnimationEnd(ViewPropertyAnimatorCompatJB.java:47) 
05-06 19:09:45.804: E/AndroidRuntime(32115): at android.view.ViewPropertyAnimator$AnimatorEventListener.onAnimationEnd(ViewPropertyAnimator.java:973) 
05-06 19:09:45.804: E/AndroidRuntime(32115): at android.animation.ValueAnimator.endAnimation(ValueAnimator.java:1012) 
05-06 19:09:45.804: E/AndroidRuntime(32115): at android.animation.ValueAnimator.access$400(ValueAnimator.java:51) 
05-06 19:09:45.804: E/AndroidRuntime(32115): at android.animation.ValueAnimator$AnimationHandler.doAnimationFrame(ValueAnimator.java:623) 
05-06 19:09:45.804: E/AndroidRuntime(32115): at android.animation.ValueAnimator$AnimationHandler.run(ValueAnimator.java:639) 
05-06 19:09:45.804: E/AndroidRuntime(32115): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:776) 
05-06 19:09:45.804: E/AndroidRuntime(32115): at android.view.Choreographer.doCallbacks(Choreographer.java:579) 
05-06 19:09:45.804: E/AndroidRuntime(32115): at android.view.Choreographer.doFrame(Choreographer.java:547) 
05-06 19:09:45.804: E/AndroidRuntime(32115): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:762) 
05-06 19:09:45.804: E/AndroidRuntime(32115): at android.os.Handler.handleCallback(Handler.java:725) 
05-06 19:09:45.804: E/AndroidRuntime(32115): at android.os.Handler.dispatchMessage(Handler.java:92) 
05-06 19:09:45.804: E/AndroidRuntime(32115): at android.os.Looper.loop(Looper.java:153) 
05-06 19:09:45.804: E/AndroidRuntime(32115): at android.app.ActivityThread.main(ActivityThread.java:5297) 
05-06 19:09:45.804: E/AndroidRuntime(32115): at java.lang.reflect.Method.invokeNative(Native Method) 
05-06 19:09:45.804: E/AndroidRuntime(32115): at java.lang.reflect.Method.invoke(Method.java:511) 
05-06 19:09:45.804: E/AndroidRuntime(32115): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833) 
05-06 19:09:45.804: E/AndroidRuntime(32115): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600) 
05-06 19:09:45.804: E/AndroidRuntime(32115): at dalvik.system.NativeStart.main(Native Method) 

ich die Lösung für diese finden gesucht, aber konnte keine passende Antwort finden.

+2

Ich bin mit dieser gerade jetzt konfrontiert. Das ist ein Problem mit dem Animator. Irgendwann wirft es irgendwann nicht, ich weiß nicht, wie ich das beheben kann :( – Krit

Antwort

1

adapter.notifyItemChanged(position); muss vom Hauptthread

anstelle von Ihrem Handler verwenden, um die Handler mit mainLooper

new Handler(Looper.getMainLooper()).post(new Runnable() { 
     @Override 
     public void run() { 
      //HERE 
     } 
    }); 
+0

Ich kümmere mich immer um diese Dinge, um sie im UI-Thread aufzurufen. Das ist kein Problem –

7

Wir hatten dieses Problem auch auf unserer Anwendung, und nach einer wirklich langen Debug-Sitzung aufgerufen werden wir fanden heraus, dass es durch adapter.setHasStableIds(true)

verursacht wurde Wir haben die beanstandete Zeile entfernt und das Problem ist endlich vorbei.

Ich hoffe, es hilft.

+1

Mein Problem gelöst, obwohl die getItemId() korrekt zurückgegeben wurde eindeutig IDs für Datenelemente – southerton

+0

Wirklich gute Antwort. IDK, wo Sie das gefunden haben. –

+0

Ich mache: "nach einer wirklich langen Debugging-Sitzung": D –

0

Es gibt mehrere Abhilfen für das Problem:

  1. Anruf zu notifyDataSetChanged() statt notifyItemChanged(). Es ist der weniger effiziente Weg, um es zu lösen.

  2. Wie von Henrique de Sousa hingewiesen, entfernen Sie die Linie adapter.setHasStableIds(true) verhindert das Problem.

Aber die wirkliche Lösung (wie durch Southerton kommentiert), wenn der Adapter stabil ist, zu implementieren und richtig getItemId(), zu Ehren des „hasStableIds“ eingestellte Wert.