Исключение RejectedExecutionException при загрузке растровых изображений для ListView с помощью AsyncTask

#java #android #android-listview #android-asynctask #android-bitmap

#java #Android #android-listview #android-asynctask #android-bitmap

Вопрос:

Я пытаюсь создать ListView с растровыми изображениями, которые генерируются по требованию. Я использую https://github.com/chrisbanes/Android-BitmapCache для кэширования растровых изображений

Я использую SimpleAdapter, с этим :

 setViewBinder(new SimpleAdapter.ViewBinder() {
 @Override
 public boolean setViewValue(View view, Object object,String string) {
     if( string.startsWith("ClassName:") ){
         final ImageView yourImageView=(ImageView) view;
         AsyncTask<String, Void, Bitmap> imageLoadAsyncTask = new AsyncTask<String, Void, Bitmap>() {
             String cname;
             @Override
             protected Bitmap doInBackground(String... classnames) {
                 cname=classnames[0];
                 return db.getCharIcon(classnames[0]);
             }

             @Override
             protected void onPostExecute(Bitmap bitmap) {
                 yourImageView.setImageBitmap(bitmap);
             }
         };
         imageLoadAsyncTask.execute(string.substring(TextUtils.getTrimmedLength("ClassName:")));
         return true;
     }
     return false;
    }
}
  

функция getCharIcon находится здесь :

 Bitmap getCharIcon(String classname){
    Bitmap modBmp;
    CacheableBitmapDrawable cacheBmp=mCache.get(classname);
    if(cacheBmp==null)
    {
        modBmp=createCharIcon(classname);
        mCache.put(classname,modBmp);
    }
    else
    {
        modBmp=cacheBmp.getBitmap();
    }
    return modBmp;
}
  

где createCharIcon генерирует растровое изображение таким образом (мне еще предстоит реализовать окончательную версию, которая выбирает большую часть изображения):

 Bitmap createCharIcon(String classname)
{
    Bitmap modBmp = Bitmap.createBitmap(srcBmp,0,0,60,60);
    return modBmp;
}
  

К сожалению, я получаю эту ошибку :

 07-02 14:13:04.248  11592-11592/com.lectem.gecharacters E/AndroidRuntime﹕ FATAL EXCEPTION: main
    java.util.concurrent.RejectedExecutionException
            at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:1876)
            at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:774)
            at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1295)
            at android.os.AsyncTask.execute(AsyncTask.java:394)
            at com.lectem.gecharacters.CharFragment$1.setViewValue(CharFragment.java:110)
            at android.widget.SimpleAdapter.bindView(SimpleAdapter.java:168)
            at android.widget.SimpleAdapter.createViewFromResource(SimpleAdapter.java:126)
            at android.widget.SimpleAdapter.getView(SimpleAdapter.java:114)
            at android.widget.AbsListView.obtainView(AbsListView.java:1294)
            at android.widget.ListView.makeAndAddView(ListView.java:1730)
            at android.widget.ListView.fillDown(ListView.java:655)
            at android.widget.ListView.fillSpecific(ListView.java:1287)
            at android.widget.ListView.layoutChildren(ListView.java:1573)
            at android.widget.AbsListView.onLayout(AbsListView.java:1147)
            at android.view.View.layout(View.java:7035)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
            at android.view.View.layout(View.java:7035)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
            at android.view.View.layout(View.java:7035)
            at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1252)
            at android.widget.LinearLayout.layoutHorizontal(LinearLayout.java:1241)
            at android.widget.LinearLayout.onLayout(LinearLayout.java:1047)
            at android.view.View.layout(View.java:7035)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
            at android.view.View.layout(View.java:7035)
            at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1252)
            at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1128)
            at android.widget.LinearLayout.onLayout(LinearLayout.java:1045)
            at android.view.View.layout(View.java:7035)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
            at android.view.View.layout(View.java:7035)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
            at android.view.View.layout(View.java:7035)
            at android.view.ViewRoot.performTraversals(ViewRoot.java:1045)
            at android.view.ViewRoot.handleMessage(ViewRoot.java:1727)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:123)
            at android.app.ActivityThread.main(ActivityThread.java:4627)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:521)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
            at dalvik.system.NativeStart.main(Native Method)
  

Я получаю эту ошибку, когда слишком быстро прокручиваю список назад, поэтому я полагаю, что это связано с количеством асинхронных задач, которые я могу использовать…
Я действительно не уверен, так ли я должен это делать или нет, но библиотека bitmapLruCache должна запускаться на чем-то другом, кроме основного потока.

Ответ №1:

Обычно эта ошибка означает, что вы пытаетесь использовать слишком много AsyncTasks одновременно. В AdapterView это может произойти, если вы разветвляете AsyncTask для каждого элемента (например, для каждой строки в ListView ) без учета повторного использования строк, и пользователь выбрасывает список.

Цитирование документации библиотеки:

Если вы хотите, чтобы библиотека и функция утилизации работали, вы ДОЛЖНЫ использовать связанный CacheableImageView везде, где это возможно.

Поскольку вы, похоже, используете это в AdapterView , пожалуйста, убедитесь, что вы используете CacheableImageView .

Комментарии:

1. Казалось бы, это было бы правильно, но если я изменю окончательный вид ImageView yourImageView= (ImageView); на окончательный вид CacheableImageView yourImageView=(CacheableImageView); он выдает исключение java.lang. ClassCastException: android.widget. Просмотр изображений

2. @Lectem: вам также необходимо изменить свой макет или где бы он ни ImageView создавался, для использования CacheableImageView . Или переключитесь на библиотеку, подобную Picasso, которая не требует пользовательского ImageView класса для обработки этого случая.

3. Я попытался изменить макет, но получаю сообщение об ошибке, поскольку оно не распознано… Я думаю, что я просто отключу кэширование диска. Я взглянул на Picasso, но мне показалось, что использовать его для моих целей немного сложнее. Может быть, мне следует взглянуть поближе…

4. @Lectem: «Я получаю сообщение об ошибке, поскольку оно не распознано» — убедитесь, что вы полностью указали имя класса в элементе XML ( <uk.co.senab.bitmapcache.CacheableImageView> ).

5. Кажется, работает, но я все еще получаю исключение RejectedExecutionException. Я могу позволить себе не использовать diskcache, но было бы интересно найти решение, хотя