如何有效地加载gridview中的互联网图像?

时间:2010-11-19 14:14:47

标签: android gridview

我正在使用以下示例在我的活动中显示互联网图像。

http://developer.android.com/resources/tutorials/views/hello-gridview.html

在自定义图像适配器中,我直接从互联网上加载图像并将其分配给imageview。

在gridview中显示图像,并且每件事情都很好,但效率不高。

当我滚动gridview时,它会一次又一次地加载图像,这就是为什么gridview滚动非常慢

是否有缓存或一些有用的技术可以让它更快?

3 个答案:

答案 0 :(得分:13)

创建一个返回Bitmap的全局静态方法。此方法将采用参数:contextimageUrlimageName

方法中的

  1. 检查文件是否已存在于缓存中。如果是,返回位图

        if(new File(context.getCacheDir(), imageName).exists())
            return BitmapFactory.decodeFile(new File(context.getCacheDir(), imageName).getPath());
    
  2. 否则您必须从Web加载图像,并将其保存到缓存中:

    image = BitmapFactory.decodeStream(HttpClient.fetchInputStream(imageUrl));
    
    
    
    FileOutputStream fos = null;
    try {
        fos = new FileOutputStream(new File(context.getCacheDir(), imageName));
    }
    
    
    //this should never happen
    catch(FileNotFoundException e) {
        if(Constants.LOGGING)
            Log.e(TAG, e.toString(), e);
    }
    
    
    //if the file couldn't be saved
    if(!image.compress(Bitmap.CompressFormat.JPEG, 100, fos)) {
        Log.e(TAG, "The image could not be saved: " + imageName + " - " + imageUrl);
        image = BitmapFactory.decodeResource(context.getResources(), R.drawable.default_cached_image);
    }
    fos.flush();
    fos.close();
    
    
    return image;
    
  3. 使用FileOutputStream fos = null; try { fos = new FileOutputStream(new File(context.getCacheDir(), imageName)); } //this should never happen catch(FileNotFoundException e) { if(Constants.LOGGING) Log.e(TAG, e.toString(), e); } //if the file couldn't be saved if(!image.compress(Bitmap.CompressFormat.JPEG, 100, fos)) { Log.e(TAG, "The image could not be saved: " + imageName + " - " + imageUrl); image = BitmapFactory.decodeResource(context.getResources(), R.drawable.default_cached_image); } fos.flush(); fos.close(); return image; 类中的上述方法预加载包含所有位图的Vector<SoftReference<Bitmap>>对象,并使用另一个AsyncTask预先加载List imageUrls和imageNames(用于稍后在需要重新加载图像时访问),然后设置Map适配器。

    我建议使用GridView数组来减少使用的内存量。如果你有大量的位图,你可能会遇到内存问题。

    所以在您的SoftReferences方法中,您可能会有类似的内容(getViewicons持有类型Vector

    SoftReference<Bitmap>

    你需要做一个检查:

    myImageView.setImageBitmap(icons.get(position).get());
    
    if(icons.get(position).get() == null) { myImageView.setImageBitmap(defaultBitmap); new ReloadImageTask(context).execute(position); } ReloadImageTask课程中的

    ,只需使用正确的参数调用从上面创建的全局方法,然后在AsyncTask中调用notifyDataSetChanged

    可能需要完成一些额外的工作,以确保在已经为特定项目运行时不启动此AsyncTask

答案 1 :(得分:0)

您需要自己实施缓存。创建将下载图像的代理类。在getView中,请求此类通过传递URL来下载图像。在代理类中创建一个HashMap,它将URL映射到Bitmap。如果传递的URL的密钥不存在,请下载映像并存储它。否则返回存储的位图转换为imageView。

当然,您无法存储任意数量的图像。您需要根据预期的图像大小设置限制,例如10个图像。超过限制时,您需要丢弃旧图像,而不是新图像。

答案 2 :(得分:0)

你可以尝试DroidFu。我的应用程序使用ImageCache。还有一些基于Web的imageview或库中的某种方式。特别参见WebImageView和WebGalleryAdapter:http://mttkay.github.com/droid-fu/index-all.html

编辑添加:droid-fu项目已弃用,支持Ignition。 https://github.com/mttkay/ignition