AsyncTask管理从Amazon S3下载的图片

时间:2014-08-07 17:06:45

标签: android amazon-web-services android-asynctask amazon-s3

我有一个listView,其中每行包含一张图片(图片可以与其他行相同),这些图片是通过AsyncTask从Amazon S3单独下载的。

问题是我不知道如何管理这些下载,因为我启动了AsyncTask来获取适配器中每一行(在getView中)的图片,因此我的AsyncTask可以下载多次已下载的图片。

我想知道的是如何在下载图片时从我的AsyncTask通知我的适配器:广播,处理程序,监听器,以及如何实现它?

我想我需要有一个地图,我把文件名放在下载的开头(所以当另一行启动AsyncTask我可以知道图片正在下载时),但是如何在下载时通知适配器结束了吗?

public class AmazonAsyncTask extends AsyncTask<Void, Void, Bitmap> {

Context context;
Fragment fragment;

ImageView view;
String picture;
ProgressBar progressBar;

public AmazonAsyncTask(Context context, String picture) {
    this.context = context;
    this.picture = picture;
}

public AmazonAsyncTask(Fragment fragment, String picture) {
    this.fragment = fragment;
    this.picture = picture;
}

public AmazonAsyncTask(Context context, ImageView view, ProgressBar progressBar,
        String picture) {
    this.view = view;
    this.progressBar = progressBar;
    this.picture = picture;
}

@Override
protected Bitmap doInBackground(Void... arg0) {

    //STORE ON SD CARD
    String extr = Environment.getExternalStorageDirectory().toString();
    File mFolder = new File(extr + "/Folder");

    if (!mFolder.exists()) {
        mFolder.mkdir();
    }

    String strF = mFolder.getAbsolutePath();
    File mSubFolder = new File(strF + "/pictures");

    if (!mSubFolder.exists()) {
        mSubFolder.mkdir();
    }

    if(!"".equals(picture)){
         String s = picture;

         File f = new File(mSubFolder.getAbsolutePath(),s);

         Bitmap bitmap = AppController.getInstance().getBitmapFromMemCache(picture);
         if(bitmap == null){
            String bucketName = "my_bucket_name";
            try {
                S3Object object = AppController.getInstance().getAmazonS3().getObject(new GetObjectRequest(bucketName,"pictures/" + picture));
                InputStream is = object.getObjectContent();                     

                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inPreferredConfig = Bitmap.Config.ARGB_8888;
                bitmap = BitmapFactory.decodeStream(is, null, options);
                is.close();     

                FileOutputStream fOut = new FileOutputStream(f);
                bitmap.compress(Bitmap.CompressFormat.PNG, 90, fOut);
                fOut.flush();
                fOut.close();

                AppController.getInstance().addBitmapToMemoryCache(picture, bitmap);
                return bitmap;
            } catch (Exception ase) {
                return null;
            }
         } else return bitmap;
    } else return null;
}

@Override
protected void onPreExecute() {
    // TODO Auto-generated method stub
    super.onPreExecute();
}

@Override
protected void onPostExecute(Bitmap result) {
    // TODO Auto-generated method stub
    super.onPostExecute(result);
}

}

2 个答案:

答案 0 :(得分:0)

private interface BitmapDownloadListener {
          public void onBitmapDownloaded(Bitmap bit);

添加到AsyncTask

private BitmapDownloadListener mListener;

public void setListener(BitmapDownloadListener listener) {
      mListener = listener;
}

添加到onPostExecute(Bitmap result)

if(mListener != null) { onBitmapDownloaded(result); }

覆盖适配器内部的函数,现在添加到getView ..

AmazonAsyncTask task = new AmazonAsyncTask();
task.setListener(new BitmapDownloadResponse());
....
....

class BitmapDownloadResponse implements BitmapDownloadListener {

     public void onBitmapDownloaded(Bitmap bit) {

          .......
      }

 }

这将创建一个简单的回调适配器,所以当你完成下载后,它会发送覆盖的函数Bitmap。 您可以向监听器添加变量,例如,如果您需要可以发送它的位置......

答案 1 :(得分:0)

或者,您可以使用Picasso将图像下载到视图中。它是一个非常棒的简单库,可以在getView()中用于异步下载图像,而无需通知适配器或任何东西。

您的getView()将是这样的:

@Override public void getView(int position, View convertView, ViewGroup parent) {
SquaredImageView view = (SquaredImageView) convertView;
  if (view == null) {
     view = new SquaredImageView(context);
  }
  String url = getItem(position);

  Picasso.with(context).load(url).into(view);
}

<强>更新

由于Picasso无法下载图片,因此您可以使用EventBus之类的内容来处理回调和通知。

您可以定义一个事件,其中的图像将被传递:

public class ImageEvent {
   Bitmap bitmap;

   //...
}

将您的活动或片段注册到总线并在其中添加处理程序以将图像存储到缓存中:

public class YourActivity {

   //...

   public void onCreate(...) {
      //...
      EventBus.getDefault.register(this);
   }

   //...

   public void onEvent(ImageEvent imgEvent) {
      AppController.getInstance().addBitmapToMemoryCache(picture, imgEvent.getImage());
      adapter.notifyDataSetChanged();
   }
}

(您可以将此处理方法放在适配器类中)

现在,剩下的就是负责下载图像的类,创建ImageEvent,将图像放入其中并将其发布到EvenBus:

ImageEvent imgEvent = new ImageEvent();
imgEvent.setImage(downloadedImage);
EventBus.getDefault.post(imgEvent);

然后,EventBus将调用处理程序,并将您的图像放在缓存中,以便在应用程序的任何部分中使用。