代码之家  ›  专栏  ›  技术社区  ›  UMAR-MOBITSOLUTIONS

如何在GridView中高效加载Internet图像?

  •  7
  • UMAR-MOBITSOLUTIONS  · 技术社区  · 15 年前

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

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

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

    它在网格视图中显示图像,每件事都很好,但这不是一种有效的方法。

    每当我滚动一次又一次的GridView时,它就会加载图像,这就是为什么GridView滚动速度非常慢的原因。

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

    3 回复  |  直到 13 年前
        1
  •  13
  •   james    15 年前

    创建返回位图的全局和静态方法。此方法将采用以下参数: context , imageUrl imageName .

    在该方法中:

    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;
      

    预加载A Vector<SoftReference<Bitmap>> 对象中使用上述方法的所有位图 AsyncTask 班级,还有另一个 List 握住 Map 图像URL和图像名称(供以后需要重新加载图像时访问),然后设置 GridView 适配器。

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

    所以在你 getView 方法,您可能有类似的 icons 是一个 Vector 保持型 SoftReference<Bitmap> :

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

    您需要检查:

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

    ReloadImageTask 异步任务 类,只需使用正确的参数调用上面创建的全局方法,然后 notifyDataSetChanged 在里面 onPostExecute

    可能需要做一些额外的工作,以确保在异步任务已经针对特定项运行时不启动它。

        2
  •  0
  •   kgiannakakis    15 年前

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

    当然,你买不起像你喜欢的那样多的图片。您需要根据预期的图像大小设置限制,例如10个图像。当超过限制时,您需要放弃旧的图像而选择新的图像。

        3
  •  0
  •   Jon O    13 年前

    你可以试试卓立夫。我的应用程序使用ImageCache。还有一些基于Web的ImageView或者库中的类似的东西。请特别参见WebImageView和WebGalleryAdapter: http://mttkay.github.com/droid-fu/index-all.html

    编辑后补充:该机器人傅项目被否决,赞成点火。 https://github.com/mttkay/ignition