Amr*_*dri 24 android recycler-adapter android-recyclerview
我RecyclerView
用作列表来显示可以下载的歌曲.每个项目都有ProgressBar
它View
.当下载开始时,我使用a Handler
来通知每个项目更新ProgressBar
以显示歌曲下载进度.
Q1.这是一种正确的方法吗?还是有其他方法可以更恰当地做到这一点.
Q2.当我们
adapter.notifyItemChanged(position);
用来更新单个项目的内容时,RecyclerView会崩溃.它是从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)
Run Code Online (Sandbox Code Playgroud)
我搜索找到了解决方案但找不到合适的答案.
Hen*_*usa 12
我们的应用程序也遇到了这个问题,经过一段很长的调试后我们发现它是由它引起的adapter.setHasStableIds(true)
我们删除了违规行,问题终于消失了.
希望能帮助到你.
我遇到了同样的问题,但结果发现原因是打电话scrollToPosition
。经过多次尝试后,对我有用的解决方案是在滚动之前调用notifyDataSetChanged
(当然全部来自 UI 线程)。也许它会对某人有所帮助。
这里有人说“android:animateLayoutChanges”不应该设置为true,但我没有设置它,将它设置为false也没有帮助。
无论如何,出于某种原因,在我的情况下,用 LinearLayout 替换 ConstraintLayout 作为 RecyclerView 的父级已经修复了它。
另一种选择是,在我让 RecyclerView 的适配器对其进行任何更改或对 RecyclerView 的父级进行任何更改之前(在我的情况下,我在 ViewAnimator 中的视图之间切换),我添加了以下检查:
if (recyclerView.isAnimating)
Handler().post {
adapter.items = it.listItems
adapter.notifyDataSetChanged()
}
else {
adapter.items = it.listItems
adapter.notifyDataSetChanged()
}
Run Code Online (Sandbox Code Playgroud)
出于某种原因,这个替代方案在 POC 上对我不起作用,所以我建议改用 LinearLayout 解决方案,或者在您清除数据或像我一样切换到另一个视图时使用它:
val itemAnimator = recyclerView.itemAnimator
recyclerView.itemAnimator = null
clearItems()
recyclerView.itemAnimator = itemAnimator
Run Code Online (Sandbox Code Playgroud)
fun clearItems() {
items.clear()
recyclerView.adapter!!.notifyDataSetChanged()
viewSwitcher.setViewToSwitchTo(R.id.emptyView)
}
Run Code Online (Sandbox Code Playgroud)
我在这里向 Google 报告了这个问题。POC 和解决方法(对我有用)也在那里可用。
POC 显示,如果 RecyclerView 位于 ConstraintLayout 内,即 ViewAnimator 内,则会发生这种情况。场景是,虽然 RecyclerView 正在为其某些视图设置动画(例如,删除单个项目),但我清除了它的所有项目并切换到 ViewAnimator 中的另一个视图。
由于这是第一篇文章,我将发布另一个解决方案来解决这个问题,这对我的具体情况有帮助:我隐藏了parentview
包含recyclerview
使用
parentView.setVisibility(View.GONE);
recyclerview 不喜欢这样,显然如果你想隐藏包含 recyclerview 的视图,你只能使用View.INVISIBLE
.
adapter.notifyItemChanged(position);
必须从主线程调用
使用带有 mainLooper 的 Handler 代替您的 Handler
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
//HERE
}
});
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
8505 次 |
最近记录: |