您的位置:首页 > 理论基础 > 计算机网络

ListView如何加载网络图片,防止内存溢出

2014-02-10 16:50 274 查看
  首先是源代码的下载地址:http://download.csdn.net/detail/iloveyoueveryday/6910147 。

  打开源码,可以看到:

    


  然后来看源代码的目录,再介绍ListView之前,先说一些准备工作。

  Cache类是为图片缓存准备的,此程序会把网络图片存在SD卡的.klcz目录下(使用FileHandler类进行操作),然后将图片信息存到本地数据库(使用CacheHandler类进行操作),并将长期(比如7天)未使用的图片缓存删除。
  Cache类的属性如下:

/** 数据库中的ID */
private int id;

/** 图片的网络路径 */
private String picture;

/** 保存路径 */
private String local;

/** 更新时间 */
private Date update_time;

  Session类是一个单例类,主要用于存储全局数据。我最初创建他是为了方便存储和修改常用的登录后的用户数据。但现在发现,他的用处很大,这里也略微用到了一点,就拿过来直接用了。

  然后开始介绍重点。

  首先是ImageResource单例类,这个类是用来加载图片资源的。它使用LruCache将加载的图片资源进行保存,下次使用时直接拿出来用,无需重复加载,并且能够管理内存,当图片多于预先设置的最大可使用内存时,它会将最长时间未使用的图片内存释放掉,从而节约内存。此程序通过本类来加载本地和网络图片。(ImageResource类还提供了别的有用的功能,是我花了好长时间写的,仅供大家参考)

  接下来距离正题更近一步了。看看这个内部类:
class ViewHolder {
public TextView text;
public ImageView image;
}

  ViewHolder是自定义的内部类。大家都知道,当你上拉或者下拉ListView的时候,都会重新加载新出现的Item的getView方法,如果每次执行getView方法,都重新加载布局,肯定会浪费时间和内存,ViewHolder就是为了防止重新加载布局而建立的。接下来会说到它的用法。

  下面看核心代码,getView方法:
@Override
public View getView(int position, View convertView, ViewGroup parent) {

ViewHolder holder = null;

if(convertView == null){
// 不存在则加载新布局
LayoutInflater inflater = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.item_pic_list, null);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.item_title);
holder.image = (ImageView) convertView.findViewById(R.id.item_image);
convertView.setTag(holder);
} else {
// 存在则加载原来布局,布局重用,无需重复加载
holder = (ViewHolder) convertView.getTag();
}

int no = position + 1;
holder.text.setText("图片列表测试:" + no);
// ir是i5suoi库中ImageResource的实例,专门负责单例加载图片资源,并及时释放长时间不用的图片内存
// 先设置成默认图片,以便能够将列表中不显示在屏幕上的图片及时回收
holder.image.setImageBitmap(ir.getBitmap(getResources(), R.drawable.ic_launcher));
// 加载并显示网络图片,每个图片只加载一次,然后存到本地缓存
ir.getBitmap(holder.image, pic.replace("_num", "" + no % 60),
holder.image.getWidth(), holder.image.getHeight());

return convertView;
}


  代码注释很清晰,这里就不多做解释,只说一些注意事项。首先是本地的图片也要用ImageResource加载,才能保证每个图片只加载一次,不浪费资源和内存。其次,也是最重要的,虽然不用每次重新加载布局,但是有必要将图片重新设置成默认的,表示原来的图片暂不使用了,以便系统能够在内存使用过大时及时收回当前界面不使用的图片。

  当然,本人能力有限,如果优化的不够好,欢迎网友指出,我一定会努力改正。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: