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

来源:互联网 发布:js单例模式的应用场景 编辑:程序博客网 时间:2024/04/30 09:08

  首先是源代码的下载地址: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方法:
@Overridepublic 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加载,才能保证每个图片只加载一次,不浪费资源和内存。其次,也是最重要的,虽然不用每次重新加载布局,但是有必要将图片重新设置成默认的,表示原来的图片暂不使用了,以便系统能够在内存使用过大时及时收回当前界面不使用的图片。
  当然,本人能力有限,如果优化的不够好,欢迎网友指出,我一定会努力改正。


1 0
原创粉丝点击