java.lang.IllegalStateException:已在池中

时间:2019-04-21 13:48:39

标签: android android-recyclerview recycler-adapter

我正面临这场奇怪的崩溃。这是崩溃堆栈。我无法理解为什么它崩溃了,也无法重现此崩溃。它发生在notifyItemChanged(i)

  Fatal Exception: java.lang.IllegalStateException: Already in the pool!
   at androidx.core.util.Pools$SimplePool.release(Pools.java:117)
   at androidx.recyclerview.widget.AdapterHelper.recycleUpdateOp(AdapterHelper.java:743)
   at androidx.recyclerview.widget.AdapterHelper.recycleUpdateOpsAndClearList(AdapterHelper.java:750)
   at androidx.recyclerview.widget.AdapterHelper.consumePostponedUpdates(AdapterHelper.java:123)
   at androidx.recyclerview.widget.AdapterHelper.consumeUpdatesInOnePass(AdapterHelper.java:557)
   at androidx.recyclerview.widget.RecyclerView.processAdapterUpdatesAndSetAnimationFlags(RecyclerView.java:3585)
   at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep1(RecyclerView.java:3829)
   at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3639)
   at androidx.recyclerview.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:1877)
   at androidx.recyclerview.widget.RecyclerView$ViewFlinger.run(RecyclerView.java:5044)
   at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1092)
   at android.view.Choreographer.doCallbacks(Choreographer.java:893)
   at android.view.Choreographer.doFrame(Choreographer.java:809)
   at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1078)
   at android.os.Handler.handleCallback(Handler.java:891)
   at android.os.Handler.dispatchMessage(Handler.java:102)
   at android.os.Looper.loop(Looper.java:207)
   at android.app.ActivityThread.main(ActivityThread.java:7539)
   at java.lang.reflect.Method.invoke(Method.java)
   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:958)

4 个答案:

答案 0 :(得分:2)

当两个不同的线程试图到达您的回收视图实例以对其进行更新时,将引发异常。

让我们澄清一下。假设线程A去更新您的回收视图,然后下一个线程B尝试执行与A相同的操作。结果,抛出异常,说池中已经有A(Already in the pool!

经过一些研究以找到解决方案,我找到了这些方法

Synchronized Methods

synchronized(recycleview)
{

}

Pools.SynchronizedPool

使用androidx.core.util.Pools.SynchronizedPool<T>代替androidx.core.util.Pools.SimplePool

两种方法都试图同步访问关键部分,以避免引发异常。

答案 1 :(得分:0)

以下两个选项之一可以解决您的问题:

首先尝试将recyclerView的SupportsChangeAnimations设置为false:

((SimpleItemAnimator) RecyclerView.getItemAnimator()).setSupportsChangeAnimations(false);

否则,尝试将ItemAnimator设置为null:

recyclerView.setItemAnimator(null);
  

错误发生的可能路径:

当recycleview想要对持久项进行动画处理时,它将调用dispatchLayout()方法。 在该方法中,它将检查预测性动画,如果将其设置为false,则它将尝试从AdapterHelper类中使用UpdatesInOnePass()。并且在AdapterHelper类中,它将尝试通过调用consumperPostponedUpdates来推迟更新。因此,如果任何物品已经被回收,那么它 会给您已经存在的池错误。

答案 2 :(得分:0)

您正在更新recyclerView,同时进行计算。 您应该执行以下操作:

if (recyclerView != null) {
            recyclerView.post(new Runnable() {
                @Override
                public void run() {
                    notifyDataSetChange(); //whatever you use, insert, remove, itemChanged etc...
                }
            });
        }

答案 3 :(得分:0)

我的案例问题的根源是

thisRecycler?.getRecycledViewPool()?.clear() 调用过于频繁以至于没有在该行上执行同步操作

它是作为替代

而引入的
notifyItemRangeRemoved(0, previousContentSize)
.
.
notifyItemRangeInserted(0, newRecyclerContent.size - 1)

现在代码稳定使用

notifyItemRangeRemoved(0, previousContentSize)
.
.
notifyDataSetChanged()