1

これは Android の質問というよりは Java の質問かもしれませんが、AsyncTask 内で作成されたビットマップを取得して別のクラス (アクティビティ) に保存するのに苦労しているので、使い終わったらリサイクルできます。

AsyncTask は doInBackground() で Bitmap を作成し、onPostExecute() で ImageView のビットマップとして設定します。ImageView はコンストラクターを介して渡されます。しかし、完了後、アクティビティでビットマップにアクセスできるようにしたいと考えています。アクティビティには ImageView の ArrayList と別のビットマップがありますが、AsyncTask が新しいビットマップを作成するため、アクティビティのビットマップの ArrayList でこの新しいオブジェクトを取得する簡単な方法が見つかりません。現在、リストへのインデックスとともにArrayListをAsyncTaskコンストラクターに渡すことで機能しており、doInBackgroundは配列内のそのエントリを新しく作成されたビットマップに設定するだけです。

おそらく、アクティビティにビットマップのArrayListがない場合など、このAsyncTaskをさまざまなことに使用できるようにしたいので、このソリューションは好きではありません。また、AsyncTask コンストラクターに Bitmap を単純に与えることはできません。Java は参照を値渡しし、それを新しい Bitmap オブジェクトに設定すると、呼び出し元がアクセスできなくなるからです。

これをよりエレガントにするにはどうすればよいですか?

関連するコードは次のとおりです。この質問に関係のない行は、わかりやすくするために省略されています。

public class LoadCachedImageTask extends AsyncTask<String, Void, Void> {
    private Context context;
    private ImageView image;
    private ArrayList<Bitmap> bitmaps;
    int index;

    public LoadCachedImageTask(Context context, ImageView image, ArrayList<Bitmap> bitmaps, int index) {
        this.context = context;
        this.image = image;
        this.bitmaps = bitmaps;
        this.index = index;
    }

    protected Void doInBackground(String... urls) {
        String url = urls[0];
        Bitmap bitmap = null;

        // Create the bitmap
        File imageFile = new File(context.getCacheDir(), "test");
        bitmap = BitmapFactory.decodeFile(imageFile.getAbsolutePath());

        // Set the bitmap to the bitmap list
        bitmaps.set(index, bitmap);

        return null;
    }

    protected void onPostExecute(Void arg) {
        // Display the image
        image.setImageBitmap(bitmaps.get(index));
    }

    protected void onCancelled() {
        if (bitmaps.get(index) != null) {
            bitmaps.get(index).recycle();
            bitmaps.set(index, null);
        }
    }
}

そして、これを使用するサンプル アクティビティを次に示します。

public class SampleActivity extends Activity {
    private ArrayList<ImageView> images;
    private ArrayList<Bitmap> bitmaps;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        images = new ArrayList<ImageView>();
        bitmaps = new ArrayList<Bitmap>();
        int numImages = 15;

        // Create the images and bitmaps
        for (int i = 0; i < numImages; i++) {
            images.add(new ImageView(this));
            bitmaps.add(null);
        }

        // Load the bitmaps
        for (int i = 0; i < numImages; i++) {
            new LoadCachedImageTask(this, images.get(i), bitmaps, i).execute("http://random.image.url");
        }
    }
}

上記のコードをテストしていないので、うまくいかないかもしれませんが、要点はわかると思います。

4

1 に答える 1

1

私が理解しているように、多数のビットマップを多数のImageViews非同期にロードしようとしています。AsyncTaskこれは、それぞれに対して複数回使用する単一のクラスで実行できると思いますImageView

あなたはAsyncTask次のようになるはずです:

  public class LoadCachedImageTask extends AsyncTask<String, Void, Bitmap> {
    private final WeakReference<ImageView> mImgView;

    public LoadCachedImageTask(ImageView image) {
      mImageView = new WeakReference<ImageView>(image);
    }

    protected Void doInBackground(String... urls) {
      if(urls == null || urls.length < 1) 
        return;

      // Create the bitmap
      final Bitmap bitmap = BitmapFactory.decodeFile(url);

      return bitmap;
    }

    protected void onPostExecute(Bitmap bmp) {
        // Display the image
      if(bmp != null) {
        final ImageView imageView = (ImageView) mImgView.get();
        if(imageView != null) // needed in case the weakreference is removed
          imageView.setImageBitmap(bmp);
    }
}

次に、ImageViews の配列を次のように入力します。

for(ImageView imgView : images) {
   (new LoadCachedImageTask<String, Void, Bitmap>)(imgView).execute(getBitmapUrl());
}

for ループは各参照を繰り返し処理しImageView、新しいAsyncTask参照に渡します。次に、必要なビットマップに対して指定された URL で AsyncTask を実行します。ImageView が存在する限り、asynctask は ImageView の参照を保持します。何らかの理由で ImageView が破棄された場合でも、ビットマップはロードされ、すぐに破棄されます。

于 2012-07-26T21:17:27.830 に答える