Избежать исключения RejectedExecutionException в Android 4.4, когда приложение использует список

В Android 4.4, похоже, происходит изменение кода, который вызывает загрузку значков списков с помощью AsyncTasks. В результате многие мои пользователи на Android 4.4 получают RejectedExecutionException поскольку предел размера очереди превышен.

Умный пользователь в Code Google обнаружил это и объяснил это следующим образом:

ResolverActivity выведет RejectedExecutionException на Android 4.4.

Я просмотрел код последней ResolverActivity и заметил, что в методе ResolveListAdapter.bindView используется новый LoadIconTask (). Execute (info), это должно быть основной причиной. LoadIconTask является подклассом AsyncTask, слишком много запущенных в AsyncTask процессов вызывает RejectedExecutionException.

Изменение ResolverActivity можно найти в репозитории Android GitHub .

В моем приложении в настоящее время имеется 82 трассировки стека для RejectedExecutionException , все из которых предназначены для Android 4.4. Пример начала стека:

 java.util.concurrent.RejectedExecutionException: Task android.os.AsyncTask$3@41d44580 rejected from java.util.concurrent.ThreadPoolExecutor@41a575c0[Running, pool size = 5, active threads = 5, queued tasks = 128, completed tasks = 140] at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2011) at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:793) at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1339) at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:590) at android.os.AsyncTask.execute(AsyncTask.java:535) at com.android.internal.app.ResolverActivity$ResolveListAdapter.bindView(ResolverActivity.java:716) at com.android.internal.app.ResolverActivity$ResolveListAdapter.getView(ResolverActivity.java:702) at android.widget.AbsListView.obtainView(AbsListView.java:2255) ... 

Есть ли способ обойти или обработать это изменение?

Solutions Collecting From Web of "Избежать исключения RejectedExecutionException в Android 4.4, когда приложение использует список"

Проблема заключается в том, что различные исполнители, используемые AsyncTask в зависимости от targetSdkVersion приложения:

1) targetSdkVersion <= 12

AsyncTask.execute () использует AsyncTask.THREAD_POOL_EXECUTOR. Очередь в AsyncTask.THREAD_POOL_EXECUTOR ограничена 128 элементами. Если очередь заполнена, вызывается RejectedExecutionException. Вот что происходит здесь

2) targetSdkVersion> 12

AsyncTask использует AsyncTask.SERIAL_EXECUTOR. AsyncTask.SERIAL_EXECUTOR имеет неограниченную очередь. Поэтому в этом случае RejectedExecutionException никогда не выбрасывается.

Решение 1 (AKA – «чистое» решение)

Используйте отдельный APK с targetSdkVersion> 12 и более высокий код версии, поэтому это предпочтительнее для HONEYCOMB_MR2 и более поздних версий Android. Это заставит AsyncTask использовать ThreadPool.SERIAL_EXECUTOR на HONEYCOMB_MR2 и более поздней версии Android.

Решение 2 (AKA – грязный хак)

Просто сделайте AsyncTask.SERIAL_EXECUTOR по умолчанию, используя Reflection.

 AsyncTask.class.getMethod("setDefaultExecutor", Executor.class).invoke(null, AsyncTask.SERIAL_EXECUTOR);