如何使用从网上下载的图像自动更改图像?

时间:2014-02-13 15:16:44

标签: android android-asynctask

我必须创建一个包含下载图像的图库,我想在下载图像时显示加载图像。 我用这个适配器:

public class GridViewImageAdapter extends BaseAdapter {
Context context;
public ImageView imageView;
private Activity _activity;
private ArrayList<String> _filePaths = new ArrayList<String>();
private int imageWidth;

public GridViewImageAdapter(Activity activity, ArrayList<String> filePaths,
    int imageWidth,Context context1) {

this._activity = activity;
this._filePaths = filePaths;
this.imageWidth = imageWidth;
this.context=context1;

}

public int getCount() {
    return this._filePaths.size();
}

public Object getItem(int position) {
    return this._filePaths.get(position);
}

public long getItemId(int position) {
    return position;
}

public View getView(int position, View convertView, ViewGroup parent) {

    if (convertView == null) {
        imageView = new ImageView(_activity);
    } else {
        imageView = (ImageView) convertView;
    } 


    imageView.setBackgroundResource(R.drawable.gallery_image);

   imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
   imageView.setLayoutParams(new GridView.LayoutParams(imageWidth,imageWidth));
  Log.e("Position",position+"");
 new RetreiveBitMap().execute(_filePaths.get(position));

return imageView;
 }

class RetreiveBitMap extends AsyncTask<String,Integer,Bitmap> {

private Exception exception;
protected Bitmap doInBackground(String... urls) {

    Bitmap bm = null;
    URL myFileUrl =null;
    BitmapFactory.Options options=new BitmapFactory.Options();
        options.inSampleSize = 1;
    try {
        myFileUrl= new URL(urls[0]);
        } catch (MalformedURLException e) {
        e.printStackTrace();
        }
    try {

        String encodedfilename = Base64.encodeToString(urls[0].getBytes(),0);

    //Controllo presenza della cache
    try {
    InputStream check = context.openFileInput(encodedfilename);
    } catch (FileNotFoundException e) {
    // Se non presente, scarico il file

    HttpURLConnection conn= (HttpURLConnection)myFileUrl.openConnection();
    conn.setDoInput(true);
    conn.connect();
    InputStream is = conn.getInputStream();
     //Salvataggio cache
    FileOutputStream fos = context.openFileOutput(encodedfilename,    Context.MODE_PRIVATE);
    byte[] buffer = new byte[1024];
    int len1 = 0;
    while ( (len1 = is.read(buffer)) > 0 ) {
    fos.write(buffer,0, len1);
    }

    fos.close();
    }

     bm =     BitmapFactory.decodeStream(context.openFileInput(encodedfilename),null,options);


    } catch (IOException e) {
Log.e("errore download",e.getMessage());
    } 
    return bm;

} 
protected void onPreExecute() {

    imageView.setImageResource(R.drawable.spinner);
}

protected void onPostExecute(Bitmap imageBit) {

    imageView.setImageBitmap(imageBit);
  }
 }
}

使用此代码,只有视图中的最后一张图像会更改为下载的图像。 出现的图像应该是网格的第一个而不是最后一个!

1 个答案:

答案 0 :(得分:0)

您正在寻找的是“懒惰加载程序”的一些变体,它会在下载内容时加载内容。在GridViewListView中完成此操作并不总是那么明显,因为两种视图类型中都存在构建的视图回收优化。有几种方法可以解决这个问题。

(1)更新为支持图片网址的适配器Object中包含的每个Collection添加一个字段。最初加载默认图像,当知道网址时,更新Object中的字段并在视图上调用notifyDataSetChanged()进行更新。

(2)实现也下载图像的外部图像缓存。开始使用defalt图像显示视图。下载完成后,notifyDataSetChanged。检查getView方法中的新图像并进行更新。例如 - 使用LruCache(谷歌如何设置)

@Override
public View getView(int position, View convertView, ViewGroup parent){
    View v = convertView;
    if(v == null){
        v = activity.getLayoutInflater().inflate(R.layout.your_layout_for_view, null);
    }

    ImageView picture = v.findViewById(R.id.picture_view);
    Bitmap b = memCache.get(KEY_VALUE);
    if(b != null){
        pictureView.setImageBitmap(b);
    } else {
        picture.setImageBitmap(memCache.get(DEFAULT_IMAGE_KEY);
        if(!checkedKeyList.contains(KEY_VALUE){
            downloadPictureAndAddToCache(KEY_VALYE);
            checkedKeyList.add(KEY_VALYE);
    }

}

你会注意到上面的例子是半psudeo代码。有些方法没有定义。那是因为我不知道你试图下载图像的对象的结构。但是,一般的想法是检查外部缓存。如果包含该对象的图像(由您定义的某个唯一键定位),则使用该图像。如果未找到图像,请尝试使用AsyncTask下载该图像。我添加了List<T>代表您检查过的密钥集合。这是为了防止在没有找到图片或者对于其中一个关键值不存在的情况下出现无限循环。在每种情况下,当图片下载完成后,在适配器上调用notifyDataSetChanged()来刷新视图。您可以在AsyncTask

中的PostExecute上执行此操作