从AsyncTask中设置对新位图的引用



这可能更像是一个Java问题,而不是一个Android问题,但我在检索AsyncTask中创建的位图以存储在另一个类(活动)中时遇到了问题,以便在使用完它后可以回收它。

AsyncTask在doInBackground()中创建位图,并将其设置为onPostExecute()中ImageView的位图,ImageView通过构造函数传入。但在完成后,我希望位图可以在"活动"中访问。"活动"有一个ImageViews的ArrayList和另一个位图,但由于AsyncTask创建了一个新位图,我找不到在"活动"的位图ArrayList中获取此新对象的简单方法。目前,我的工作方式是将ArrayList和列表中的索引一起传递给AsyncTask构造函数,doInBackground只将数组中的该条目设置为新创建的位图。

不过,我不喜欢这个解决方案,因为我希望能够将这个AsyncTask用于不同的事情,也许是在"活动"没有位图的ArrayList的情况下。我不能简单地给AsyncTask构造函数一个位图,因为Java通过值传递引用,并且将其设置为新的位图对象将不允许调用方访问。

我怎样才能做得更优雅?

这是相关代码。为了清楚起见,省略了与这个问题无关的几行。

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");
        }
    }
}

我还没有测试过上面的代码,所以它可能不起作用,但我认为它能说明问题。

据我所知,您正试图将大量位图异步加载到大量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存在,异步任务就会保留对ImageView的引用。如果由于某种原因,您的ImageView被破坏,位图仍将加载,然后立即被丢弃。

最新更新