这可能更像是一个Java问题而不是Android问题,但我在检索AsyncTask中创建的Bitmap以存储在另一个类(一个Activity)时遇到问题,以便我可以在使用完毕后回收它它。
AsyncTask在doInBackground()中创建Bitmap,并将其设置为onPostExecute()中ImageView的位图,ImageView通过构造函数传入。但是在完成之后我希望在Activity中可以访问Bitmap。 Activity有一个ImageViews的ArrayList和另一个Bitmaps,但是由于AsyncTask创建了一个新的Bitmap,我找不到一种简单的方法来在Activity中的Bitmap的ArrayList中获取这个新对象。目前我通过将ArrayList与列表中的索引一起传递给AsyncTask构造函数来实现它,而doInBackground只是将数组中的条目设置为新创建的位图。
我不喜欢这个解决方案,因为我希望能够将这个AsyncTask用于不同的东西,也就是说Activity里没有Bitmap的ArrayList。而且我不能简单地给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");
}
}
}
我没有测试过上面的代码,所以它可能无法正常工作,但我认为它可以解决问题。
答案 0 :(得分: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被破坏了,那么位图仍会加载,然后立即被扔掉。