2

デバイスとWebの両方からの画像用のレイジー画像ローダーを作成しようとしていますListView。何を使用するか、そしてどのようにリクエストをプールするスレッドを使用できるかを考えています(常に実行されており、ビューとアダプターをアタッチでき、画像の読み込みを処理します)、すでにキャッシュします画像を読み込んで、読み込む前に画像の可視性をチェックするので、不要な作業をしません。

AsyncTask私はフォーラムで多くの提案のようなものを使用することについて別の考えを持っていました。ただし、欠点が1つあります。new MyTask().execute(urls); オンデマンドで画像の読み込みを開始して停止したい場合、これを使用すると問題が発生することがよくあります。イメージごとに非同期タスクを使用する場合は、イメージごとに新しい非同期タスクが必要です。これは多くの「新しい」ものであり、プールを使用できますが、スタックしている非同期タスクが多すぎる場合でも、約150を作成します- 200のasycタスク、私の好みには多すぎます...

皆さんはどう思いますか?私はスレッドがここでより良い仕事をするだろうと思います:

  1. 殺されるまで走り続ける
  2. キューからジョブを取得してみてください。ジョブでない場合は、待機してください。
  3. ジョブが利用可能な場合は、それを取得して処理を開始します。
  4. 各リクエストは単独でシリアルに処理され、スレッドをブロックします。
  5. 一度は「2」を続けます。
  6. startLoadingImage()表示する必要のあるビューを使用してアダプターによって実行される各エンキューは、新しいジョブを作成し、待機ロックで通知を呼び出します。

複数のGET\POSTリクエストを並行して実行したい場合は、スレッドのプールを使用してこのコードを最適化できます。また、次のアクセスで高速にロードするために、すでにダウンロード/ロードした画像をキャッシュしています。アイデアは、GCとリストの遅れを最小限に抑えることです。

4

2 に答える 2

2

私は次のようなものを実装しました:

/** 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());
         }
     }
}

次に、以下を使用してロードするURIを追加します。

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

于 2010-09-19T22:27:56.387 に答える
1

時期尚早の最適化を行っていると思います。必要なものを可能な限り最速の方法で実装するだけで、後でいつでも実装を改善できます。また、なぜ同時に 200 個の AsyncTasks を開始する必要があるのでしょうか? すべての画像を 1 つの画面に表示するつもりはないと思います (ListView の場合、ユーザーがリストの最後までスクロールできないのに、なぜすべての画像をロードするのでしょうか?)。

于 2010-09-19T09:44:01.483 に答える