避免RejectedExecutionException在Android 4.4系统,当应用程序使用清单应用程序、清单、系统、RejectedExecutionException

由网友(人心太拥挤)分享简介:在Android 4.4系统,似乎是在code,导致列表图标使用AsyncTasks加载的变化。其结果是,我的很多用户对Android 4.4系统的get RejectedExecutionException ,因为队列的大小超过限制。In Android 4.4 there seems to be a chang...

在Android 4.4系统,似乎是在code,导致列表图标使用AsyncTasks加载的变化。其结果是,我的很多用户对Android 4.4系统的get RejectedExecutionException ,因为队列的大小超过限制。

In Android 4.4 there seems to be a change in the code that causes list icons to be loaded using AsyncTasks. The result is that many of my users on Android 4.4 get RejectedExecutionException since the queue size limit is exceeded.

在 $ C $一个聪明的用户C谷歌发现这一点,并以这种方式解释它

A clever user at Code Google discovered this, and explained it in this way:

ResolverActivity将抛出RejectedExecutionException的Andr​​oid 4.4系统。

ResolverActivity will throw RejectedExecutionException on Android 4.4.

我看最新ResolverActivity的code和注意到,在ResolveListAdapter.bindView方法是使用新的LoadIconTask()。执行(信息),这应该是根本原因。 LoadIconTask是AsyncTask的子类,同时运行过多的AsyncTask会造成RejectedExecutionException。

I viewed the code of latest ResolverActivity and noticed that in ResolveListAdapter.bindView method it is using new LoadIconTask().execute(info), this should be the root cause. LoadIconTask is a subclass of AsyncTask, too many AsyncTask running at the same time will cause RejectedExecutionException.

该ResolverActivity变化可以在 Android的GitHub库。

The ResolverActivity change can be found at the Android GitHub repo.

我的应用程序目前对 RejectedExecutionException 82堆栈跟踪,所有这一切都为Android 4.4。栈的实例启动:

My app currently has 82 stack traces for RejectedExecutionException, all of which are for Android 4.4. Example start of stack:

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)
...

有没有办法回避或处理这种变化?

Is there any way to sidestep or handle this change?

推荐答案

问题在于不同的执行者是AsyncTask的用途,具体取决于应用程序的targetSdkVersion:

The problem lies with the different Executors that AsyncTask uses depending on targetSdkVersion of the app:

AsyncTask.execute()使用AsyncTask.THREAD_POOL_EXECUTOR。在AsyncTask.THREAD_POOL_EXECUTOR队列被限制为128个项目。如果队列已满RejectedExecutionException被抛出。这就是发生在这里。

AsyncTask.execute() uses the AsyncTask.THREAD_POOL_EXECUTOR. The queue in AsyncTask.THREAD_POOL_EXECUTOR is limited to 128 items. If the queue is full RejectedExecutionException is thrown. This is what happens here

AsyncTask的使用AsyncTask.SERIAL_EXECUTOR。 AsyncTask.SERIAL_EXECUTOR有一个无界队列。因此,在这种情况下RejectedExecutionException从不抛出。

AsyncTask uses the AsyncTask.SERIAL_EXECUTOR. AsyncTask.SERIAL_EXECUTOR has an unbounded queue. So in this scenario RejectedExecutionException is never thrown.

使用一个单独的APK与targetSdkVersion> 12和更高的版本code所以这是preferred的HONEYCOMB_MR2和更高版本的Andr​​oid系统。这将导致AsyncTask的使用ThreadPool.SERIAL_EXECUTOR上HONEYCOMB_MR2和更高的Andr​​oid版本。

Use a separate APK with targetSdkVersion > 12 and a higher versionCode so that is preferred for HONEYCOMB_MR2 and later versions of Android. This will cause AsyncTask to use ThreadPool.SERIAL_EXECUTOR on HONEYCOMB_MR2 and later version of Android.

只需使用反射使AsyncTask.SERIAL_EXECUTOR默认的​​。

Just make AsyncTask.SERIAL_EXECUTOR the default using Reflection.

AsyncTask.class.getMethod("setDefaultExecutor", Executor.class).invoke(null, AsyncTask.SERIAL_EXECUTOR);
阅读全文

相关推荐

最新文章