Проблемы с производительностью AsyncTask на многих порождениях AsyncTask. - PullRequest
2 голосов
/ 19 сентября 2010

Я пытаюсь создать загрузчик ленивых изображений для изображений как с устройства, так и из Интернета для ListView. Я думаю о том, что использовать и как, с одной стороны, я могу использовать поток, который объединяет мой запрос (всегда выполняется, и я могу прикрепить представление и адаптер, и он будет обрабатывать загрузку изображения для меня), кэшировать уже загруженные изображения и проверяет видимость изображений перед загрузкой, поэтому я не буду выполнять ненужную работу.

У меня была еще одна мысль об использовании AsyncTask, как многие предлагают на форуме. Однако есть один недостаток. Я вижу, что многие используют new MyTask().execute(urls);, это создает проблему, если я хочу начать загрузку и прекратить загрузку изображений по требованию. Если я использую асинхронную задачу для каждого изображения, тогда мне нужно новое асинхронное задание для каждого изображения, это много нового, что я могу сделать, я могу использовать пул, но если слишком много асинхронных задач застрянет, я все равно создаю около 150- 200 асинхронных заданий, слишком много на мой вкус ...

Что вы, ребята, думаете? Я думаю, что нить сделает лучше работу здесь:

  1. Продолжайте бежать, пока не убьете
  2. Попробуйте получить работу из очереди, если не работы, подождите.
  3. Если задание доступно, получите его и начните обработку.
  4. Каждый запрос обрабатывается отдельно, последовательно и блокирует поток.
  5. После того, как все продолжается с "2".
  6. Каждая постановка в очередь, выполняемая адаптером с использованием startLoadingImage() для представлений, которые необходимо отобразить, создаст новое задание и вызовет уведомление при блокировке ожидания.

Я могу оптимизировать этот код с помощью пула потоков, если мне нужно несколько запросов GET \ POST параллельно. Также я кеширую уже загруженные \ загруженные изображения для быстрой загрузки при следующем доступе. Идея состоит в том, чтобы минимизировать GC и отставание списков.

Ответы [ 2 ]

2 голосов
/ 20 сентября 2010

Я реализовал что-то вроде этого:

/** Contains all the pending requests for thumbnails. */
private LinkedList<Uri> mPendingThumbnailRequests = new LinkedList<Uri>();

private ThumbnailGetter mThmGetter = null;
/**
 * Asynchronous process for retrieving thumbnails from Uris.
 */
private class ThumbnailGetter extends AsyncTask<Uri, Integer, Uri> {
    private final String LOG_TAG = ThumbnailGetter.class
            .getSimpleName();
    /** The Uri beeing processed */
    private Uri mUri = null;
    /*
     * (non-Javadoc)
     * 
     * @see android.os.AsyncTask#doInBackground(Params[])
     */
    @Override
    protected Uri doInBackground(Uri... uris) {
        // We process Uris one after another... so the Array contains
        // only one Uri.
        mUri = uris[0];
        // Let the ThumbnailLoader do the job.
        Uri result = ItemsLoader.getThumbnail(mContext, mUri);
        return result;
    }
    /*
     * (non-Javadoc)
     * 
     * @see android.os.AsyncTask#onPostExecute(java.lang.Object)
     */
    @Override
    protected void onPostExecute(Uri result) {
        super.onPostExecute(result);
        // Give the retrieved thumbnail to the adapter...
        mImageAdapter.updateThumbUri(mUri, result);
        // then process any other pending thumbnail request.
        if (!mPendingThumbnailRequests.isEmpty()) {
            mThmGetter = new ThumbnailGetter();
            mThmGetter.execute(mPendingThumbnailRequests.poll());
         }
     }
}

Затем я добавляю Uris для загрузки, используя:

if (!mPendingThumbnailRequests.contains(imageUri)) {
    mPendingThumbnailRequests.offer(imageUri);
    if (mThmGetter == null
            || mThmGetter.getStatus() == AsyncTask.Status.FINISHED) {
        // If the previous instance of the thumbnail getter has
        // finished, start a new one.
        mHandler.sendEmptyMessage(MSG_SHOW_INDETERMINATE_PROGRESS);
        mThmGetter = new ThumbnailGetter();
        mThmGetter.execute(mPendingThumbnailRequests.poll());
    }
}

Это даже позволяет отменять запросы, используя mPendingThumbnailRequests.remove()

Полная реализация здесь: http://code.google.com/p/emailalbum/source/browse/EmailAlbumAndroid/trunk/src/com/kg/emailalbum/mobile/creator/SelectPictures.java

1 голос
/ 19 сентября 2010

Я думаю, что вы делаете преждевременную оптимизацию.Просто внедрите то, что вам нужно, как можно быстрее, вы всегда сможете улучшить реализацию позже.Кроме того, зачем вам нужно запускать 200 AsyncTasks одновременно?Я не думаю, что вы собираетесь показывать все изображения на одном экране (а в случае ListView зачем загружать все изображения, даже если пользователь никогда не сможет прокрутить до конца списка?).

...