java.lang.IllegalStateException: уже в пуле
Я сталкиваюсь с этой странной аварией на продукте в представлении переработчика при переработке предметов, и я также не могу воспроизвести эту аварию.
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)
Ответы
Ответ 1
Исключение выдается, когда два разных потока пытаются получить доступ к вашему экземпляру recycle view для его обновления.
Давайте проясним это. Поток A переходит к обновлению вашего представления корзины. Затем следующий поток B пытается сделать то же самое, что и A. В результате, выдается исключение, говорится, что A уже находится в пуле (Already in the pool!
)
после некоторых исследований, чтобы найти решение, я нашел эти подходы
Синхронизированные методы
synchronized(recycleview)
{
}
Pools.SynchronizedPool
используя androidx.core.util.Pools.SynchronizedPool<T>
вместо androidx.core.util.Pools.SimplePool
оба подхода пытаются синхронизировать доступ к критическому разделу во избежание исключения.
Ответ 2
Один из следующих двух вариантов может решить вашу проблему:
Сначала попробуйте установить SupportsChangeAnimations в false для recyclerView:
((SimpleItemAnimator) RecyclerView.getItemAnimator()).setSupportsChangeAnimations(false);
В противном случае попробуйте установить ItemAnimator на ноль:
recyclerView.setItemAnimator(null);
Возможные пути, откуда может прийти ошибка:
Пока recycleview хочет анимировать постоянные элементы, он вызывает метод dispatchLayout(). В этом методе он будет проверять наличие прогнозирующих анимаций и, если он установлен в значение false, он будет пытаться использоватьUpdatesInOnePass() из класса AdapterHelper. А в классе AdapterHelper он попытается отложить обновления, вызвав потреблениеPostponedUpdates. Таким образом, если какой-либо элемент уже переработан, он выдаст ошибку уже в пуле.
Ответ 3
Вы точно знаете, откуда в вашем коде появилась эта ошибка? Пожалуйста, опубликуйте пример кода для лучшего понимания.
Я бы сказал, попробуйте написать код в обработке блоков try-catch, и вы поймете, где именно вы получаете ошибку.
Спасибо!
Ответ 4
Вы обновляете recyclerView, пока он выполняет вычисления.
Вы должны сделать что-то вроде этого:
if (recyclerView != null) {
recyclerView.post(new Runnable() {
@Override
public void run() {
notifyDataSetChange(); //whatever you use, insert, remove, itemChanged etc...
}
});
}