I'm using RecyclerView
as a list to show songs that can be downloaded. Each item has ProgressBar
in its View
. When the download starts, then I use a Handler
to notify each item to update the ProgressBar
to show the song download progress.
Q1. Is this is a correct way to do it or Is there any other way to do it more appropriately.
Q2. RecyclerView gets crashed when we use
adapter.notifyItemChanged(position);
to update the content of single item. It is called from aHandler
usingRunnable
. But, the log don't show any traces for my code. Why?
Below is the log for this issue:
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)
I searched to find the solution for this but couldn't find any appropriate answer.
We also had this issue on our application, and after a really long debugging session we found out that it was caused by adapter.setHasStableIds(true)
We removed the offending line and the issue is finally gone.
Hope it helps.
i had the same issue,i could handle it by disabling the animator of recyclerview:
recyclerView.itemAnimator = null
For me the issue was resolved after I removed animateLayoutChanges=“true”
from the parent ViewGroup of the recyclerview.
Some people here say that "android:animateLayoutChanges" should not be set to true, but I didn't set it, and setting it to false didn't help either.
Anyway, for some reason, in my case, replacing ConstraintLayout with LinearLayout as the parent of the RecyclerView has fixed it.
Another alternative is that before I let the adapter of the RecyclerView have any changes on it or have any changes on the RecyclerView's parent (in my case I switch between views in ViewAnimator), I added this check:
if (recyclerView.isAnimating)
Handler().post {
adapter.items = it.listItems
adapter.notifyDataSetChanged()
}
else {
adapter.items = it.listItems
adapter.notifyDataSetChanged()
}
For some reason this alternative didn't work for me on POC, so I suggest the LinearLayout solution instead, or use this in case you clear the data or switch to another view like I do:
val itemAnimator = recyclerView.itemAnimator
recyclerView.itemAnimator = null
clearItems()
recyclerView.itemAnimator = itemAnimator
fun clearItems() {
items.clear()
recyclerView.adapter!!.notifyDataSetChanged()
viewSwitcher.setViewToSwitchTo(R.id.emptyView)
}
I reported about this issue to Google here. The POC and the workarounds (that work for me) are available there too.
The POC shows that this occurs if the RecyclerView is inside ConstraintLayout, which is inside ViewAnimator. The scenario is that while the RecyclerView is animating some of its views (removing a single item, for example), I clear all of its items and switch to another view inside the ViewAnimator.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With