【问题标题】:how to load internet images in gridview efficiently?如何有效地在gridview中加载互联网图像?
【发布时间】:2013-08-23 01:13:48
【问题描述】:

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

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

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

在gridview中显示图像,一切正常,但不是有效的方式。

每当我滚动gridview时,它会一次又一次地加载图像,这就是gridview滚动很慢的原因

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

【问题讨论】:

    标签: android gridview


    【解决方案1】:

    创建一个返回位图的全局静态方法。此方法将接受参数:contextimageUrlimageName

    在方法中:

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

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

      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;
      

    使用上述方法在AsyncTask 类中预加载带有所有位图的Vector<SoftReference<Bitmap>> 对象,以及另一个List 持有imageUrls 和imageNames 的Map(供以后需要重新加载图片),然后设置您的 GridView 适配器。

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

    所以在你的getView 方法中,你可能有类似的东西(其中iconsVector 持有类型SoftReference<Bitmap>

    myImageView.setImageBitmap(icons.get(position).get());
    

    您需要进行检查:

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

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

    可能需要做一些额外的工作,以确保您不会在该 AsyncTask 已经为特定项目运行时启动它

    【讨论】:

      【解决方案2】:

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

      当然,您无法存储任意数量的图像。您需要根据您希望拥有的图像大小设置一个限制,例如 10 个图像。当超出限制时,您需要丢弃旧图像以支持新图像。

      【讨论】:

        【解决方案3】:

        你可以试试 DroidFu。我的应用程序使用 ImageCache。图书馆中还有一些基于网络的图像视图或类似的东西。具体见 WebImageView 和 WebGalleryAdapter:http://mttkay.github.com/droid-fu/index-all.html

        编辑添加:droid-fu 项目已弃用,取而代之的是 Ignition。 https://github.com/mttkay/ignition

        【讨论】:

          猜你喜欢
          • 2013-03-14
          • 2014-01-07
          • 2013-08-22
          • 1970-01-01
          • 1970-01-01
          • 2015-11-28
          • 1970-01-01
          • 1970-01-01
          • 2011-10-15
          相关资源
          最近更新 更多