Ответ 1
У нас также была эта проблема в нашем приложении, и после очень долгого отладочного сеанса мы выяснили, что это было вызвано adapter.setHasStableIds(true)
Мы удалили строку нарушения, и проблема наконец исчезла.
Надеюсь, что это поможет.
Я использую RecyclerView
в качестве списка, чтобы показывать песни, которые можно загрузить. Каждый элемент имеет ProgressBar
в своем View
. Когда начинается загрузка, я использую Handler
для уведомления каждого элемента, чтобы обновить ProgressBar
, чтобы показать ход загрузки песни.
Q1. Это правильный способ сделать это или есть ли другой способ сделать это более подходящим образом.
Q2. RecyclerView разбивается, когда мы используем
adapter.notifyItemChanged(position);
для обновления содержимого отдельного элемента. Он вызывается изHandler
с помощьюRunnable
. Но в журнале не отображаются следы для моего кода. Почему?
Ниже приведен журнал для этой проблемы:
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)
Я искал, чтобы найти решение для этого, но не нашел подходящего ответа.
У нас также была эта проблема в нашем приложении, и после очень долгого отладочного сеанса мы выяснили, что это было вызвано adapter.setHasStableIds(true)
Мы удалили строку нарушения, и проблема наконец исчезла.
Надеюсь, что это поможет.
adapter.notifyItemChanged(position);
должен быть вызван из основного потока
вместо вашего обработчика используйте Handler с mainLooper
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
//HERE
}
});
Существует несколько способов обхода проблемы:
Вызовите notifyDataSetChanged()
вместо notifyItemChanged()
. Это менее эффективный способ его решения.
Как указано Henrique de Sousa, удалите строку adapter.setHasStableIds(true)
, чтобы предотвратить проблему.
Но реальное решение (как прокомментировано ютертон), если адаптер устойчив, заключается в том, чтобы реализовать и правильно getItemId()
, соблюдая установленное значение hasStableIds.