简单的ListView中item图片异步加载

前言:

在android开发当中,从目标地址获取图片往往都是采用异步加载的方法。当完全加载完图片后在进行显示,也有些是直接将加载的图片一点一点的显示出来。

这两个区别只是对流的处理不同而已。现在就讲讲当图片被完全获取到后在显示的方法。

一,效果图:

 

    初始化:                                                   获取后:

                       

1.1,效果思路:

初始化的时候默认ImageView显示一张白色的图片,在加载完图片以后,用心的图片将白色图片给替换掉,就达到效果了。

二,代码实现:

    主要类介绍:

    AsyncImageLoadAdapter :ListView的自定义Adapter

    AsyncLoad :图片异步加载类

    MainActivity :主Activity。

相关的布局文件就不介绍了,在后面看就行了。

MainActivity:

 1 public class MainActivity extends Activity {
 2
 3     private ListView listView;
 4
 5     @Override
 6     protected void onCreate(Bundle savedInstanceState) {
 7         super.onCreate(savedInstanceState);
 8         setContentView(R.layout.activity_main);
 9         initView();
10         initData();
11     }
12
13     private void initView() {
14         listView = (ListView) findView(R.id.listView);
15     }
16
17     private void initData() {
18         List<HashMap<String, Object>> list = new ArrayList<HashMap<String, Object>>();
19         HashMap<String, Object> map1 = new HashMap<String, Object>();
20         map1.put("img",
21                 "http://img5.imgtn.bdimg.com/it/u=747474479,3247936386&fm=21&gp=0.jpg");
22         map1.put("txt", "条目一");
23         HashMap<String, Object> map2 = new HashMap<String, Object>();
24         map2.put("img",
25                 "http://pic.nipic.com/2007-12-22/2007122215556437_2.jpg");
26         map2.put("txt", "条目二");
27         HashMap<String, Object> map3 = new HashMap<String, Object>();
28         map3.put("img",
29                 "http://img1.imgtn.bdimg.com/it/u=1774561363,2410491846&fm=21&gp=0.jpg");
30         map3.put("txt", "条目三");
31         HashMap<String, Object> map4 = new HashMap<String, Object>();
32         map4.put("img",
33                 "http://img5.imgtn.bdimg.com/it/u=112049007,3368205326&fm=21&gp=0.jpg");
34         map4.put("txt", "条目四");
35         HashMap<String, Object> map5 = new HashMap<String, Object>();
36         map5.put("img",
37                 "http://img3.imgtn.bdimg.com/it/u=2953608063,4260501712&fm=21&gp=0.jpg");
38         map5.put("txt", "条目五");
39         list.add(map1);
40         list.add(map2);
41         list.add(map3);
42         list.add(map4);
43         list.add(map5);
44         AsyncImageLoadAdapter adapter = new AsyncImageLoadAdapter(
45                 MainActivity.this, list, listView);
46         listView.setAdapter(adapter);
47     }
48
49     private <T> T findView(int id) {
50         return (T) findViewById(id);
51     }
52
53 }

这个MainActivity挺简单的,就是初始化相关控件,然后给ListView附上值而已。

AsyncImageLoadAdapter :

  

 1 public class AsyncImageLoadAdapter extends BaseAdapter {
 2
 3     private Context context;
 4
 5     private List<HashMap<String, Object>> listData;
 6
 7     private AsyncLoad asyncLoad;
 8
 9     private ListView listView;
10
11     public AsyncImageLoadAdapter(Context context1,
12             List<HashMap<String, Object>> listData1, ListView listView1) {
13         this.context = context1;
14         this.listData = listData1;
15         this.asyncLoad = AsyncLoad.instance();
16         this.listView = listView1;
17     }
18
19     @Override
20     public int getCount() {
21         return listData.size();
22     }
23
24     @Override
25     public Object getItem(int position) {
26         return listData.get(position);
27     }
28
29     @Override
30     public long getItemId(int position) {
31         return position;
32     }
33
34     @Override
35     public View getView(int position, View convertView, ViewGroup parent) {
36
37         if (convertView == null) {
38             convertView = LayoutInflater.from(context).inflate(
39                     R.layout.list_item, null);
40         }
41
42         convertView.setTag(position);
43         ImageView imageView = (ImageView) convertView
44                 .findViewById(R.id.list_item_img);
45         imageView.setBackgroundResource(R.drawable.img_black);
46         TextView textView = (TextView) convertView
47                 .findViewById(R.id.list_item_tv);
48         textView.setText("我是条目" + position);
49         HashMap<String, Object> item = listData.get(position);
50         String imageStr = (String) item.get("img");
51         asyncLoad.loadImage(position, imageStr, new ILoadListener() {
52
53             @SuppressLint("NewApi")
54             @Override
55             public void onSuccess(Integer pos, Drawable drawable) {
56                 View view = listView.findViewWithTag(pos);
57
58                 if (view != null) {
59                     ImageView img = (ImageView) view
60                             .findViewById(R.id.list_item_img);
61
62                     img.setBackground(drawable);
63                 }
64             }
65
66             @Override
67             public void onFail(String failStr) {
68                 Toast.makeText(context, "错误信息是->" + failStr, Toast.LENGTH_SHORT)
69                         .show();
70             }
71         });
72
73         return convertView;
74     }
75 }

这个Adapter中加载了一个list_item布局(adapter中未用ViewHolder,不要去纠结这个,加上也可),来初始化未加载图片的时候。主要要说的是这段代码

 1 asyncLoad.loadImage(position, imageStr, new ILoadListener() {
 2    @SuppressLint("NewApi")
 3    @Override
 4    public void onSuccess(Integer pos, Drawable drawable) {
 5     View view = listView.findViewWithTag(pos);
 6     if (view != null) {
 7      ImageView img = (ImageView) view
 8        .findViewById(R.id.list_item_img);
 9      img.setBackground(drawable);
10     }
11    }
12    @Override
13    public void onFail(String failStr) {
14     Toast.makeText(context, "错误信息是->" + failStr, Toast.LENGTH_SHORT)
15       .show();
16    }
17   });

这段代码就进行了异步去加载图片。

思路是:先将ListView中的每个item设置一个Tag,便于后面找到对应的item中imageView进行图片更新。

然后利用图片加载类去网络获取图片,获取到图片后采用接口回调的方式传回图片进行ImageView更新(UI线程中

执行的)

  AsyncLoad:

  

  1 public class AsyncLoad {
  2
  3     private static AsyncLoad asyncLoad;
  4     /**
  5      * 图片缓存容器,采用软引用,当用户手机内存不够时候,系统自动回收其所占有的内存
  6      */
  7     private HashMap<String, SoftReference<Drawable>> dataMap;
  8     /**
  9      * 用于在UI线程中进行UI更新
 10      */
 11     private Handler handler = new Handler();
 12
 13     public synchronized static AsyncLoad instance() {
 14
 15         if (asyncLoad == null)
 16             asyncLoad = new AsyncLoad();
 17         return asyncLoad;
 18
 19     }
 20
 21     public AsyncLoad() {
 22         dataMap = new HashMap<String, SoftReference<Drawable>>();
 23     }
 24
 25     // 内部接口对图片获取的监听
 26     interface ILoadListener {
 27         /**
 28          * 图片加载成功后
 29          *
 30          * @param pos
 31          *            对listView中pos位置
 32          * @param drawable
 33          *            网络加载后获取到的图片
 34          */
 35         public void onSuccess(Integer pos, Drawable drawable);
 36
 37         public void onFail(String failStr);
 38
 39     }
 40
 41     /**
 42      * 开启线程对图片进行加载
 43      *
 44      * @param pos
 45      *            listView的pos位置进行加载
 46      * @param imageStr
 47      *            图片地址
 48      * @param listener
 49      *            监听接口
 50      */
 51
 52     public void loadImage(final Integer pos, final String imageStr,
 53             final ILoadListener listener) {
 54
 55         // 开启一个线程获取图片资源
 56         new Thread(new Runnable() {
 57
 58             @Override
 59             public void run() {
 60                 try {
 61                     Thread.sleep(5000);
 62                 } catch (InterruptedException e) {
 63                     e.printStackTrace();
 64                 }
 65                 load(pos, imageStr, listener);
 66             }
 67         }).start();
 68
 69     }
 70
 71     private void load(final Integer pos, final String imageStr,
 72             final ILoadListener listener) {
 73
 74         if (dataMap.containsKey(imageStr)) {
 75
 76             SoftReference<Drawable> softReference = dataMap.get(imageStr);
 77             final Drawable d = softReference.get();
 78             if (d != null) {
 79                 handler.post(new Runnable() {
 80
 81                     @Override
 82                     public void run() {
 83
 84                         listener.onSuccess(pos, d);
 85                     }
 86                 });
 87             }
 88             return;
 89
 90         }
 91
 92         try {
 93             final Drawable d = loadImgFromUrl(imageStr);
 94             if (d != null) {
 95                 SoftReference<Drawable> soft = new SoftReference<Drawable>(d);
 96                 dataMap.put(imageStr, soft);
 97             }
 98             handler.post(new Runnable() {
 99
100                 @Override
101                 public void run() {
102
103                     listener.onSuccess(pos, d);
104
105                 }
106             });
107
108         } catch (final IOException e) {
109             e.printStackTrace();
110             // 进行错误信息回报
111             handler.post(new Runnable() {
112
113                 @Override
114                 public void run() {
115
116                     listener.onFail(e.getMessage());
117
118                 }
119             });
120
121         }
122
123     }
124
125     /**
126      * 获取网路图片资源
127      *
128      * @param url
129      * @return
130      * @throws IOException
131      */
132     private static Drawable loadImgFromUrl(String urlStr) throws IOException {
133         System.out.println("urlStr->" + urlStr);
134         URL url;
135         InputStream i = null;
136         url = new URL(urlStr);
137         i = (InputStream) url.getContent();
138         Drawable drawable = Drawable.createFromStream(i, "img");
139
140         return drawable;
141
142     }
143
144 }

要想更新界面上内容,就必须在UI线程中去更新,所以就采用handler.post方法,post里面Runnable中

run执行的代码其实是在UI线程中执行的,所以就符合android的规矩,才能进行更新

参考文章:http://blog.csdn.net/harvic880925/article/details/17766027#t7

源码下载:下载

时间: 2024-10-05 11:06:27

简单的ListView中item图片异步加载的相关文章

Android新浪微博客户端(七)——ListView中的图片异步加载、缓存

原文出自:方杰|http://fangjie.sinaapp.com/?p=193转载请注明出处 最终效果演示:http://fangjie.sinaapp.com/?page_id=54该项目代码已经放到github:https://github.com/JayFang1993/SinaWeibo 一.ListView的图片异步加载 我们都知道对每一个Weibo Item都有用户头像,而且每一条微博还可能带有图片.如果在加载列表的同时加载图片,这样有几个缺点,第一很费事,界面卡住,用户体验很不

Android ListView 图片异步加载和图片内存缓存

开发Android应用经常需要处理图片的加载问题.因为图片一般都是存放在服务器端,需要联网去加载,而这又是一个比较耗时的过程,所以Android中都是通过开启一个异步线程去加载.为了增加用户体验,给用户省流量,一般把加载完的图片先缓存下来,下次加载的时候就不需要再联网去服务器端加载.图片缓存一般分为一级缓存(即内存缓存)和二级缓存(即磁盘缓存).这里只讲一级缓存. 内存缓存就是把加载完的图片先放在手机内存中,等下次加载的时候再从内存中取出来. 优点是速度快,缺点是不能长久保存,用户退出应用程序之

android Listview 软引用SoftReference异步加载图片

首先说一下,android系统加载大量图片系统内存溢出的3中解决方法: (1)从网络或本地加载图片的时候,只加载缩略图.这个方法的确能够少占用不少内存,可是它的致命的缺点就是,因为加载的是缩略图,所以图片失真比较严重,对于对图片质量要求很高的应用,可以采用下面的方法 /** *按照图片路径加载 *@param path图片资源的存放路径 *@param scalSize缩小的倍数 *@return */ public static Bitmap loadResBitmap(String path

Android图片异步加载框架Universal Image Loader的源码分析

项目地址:https://github.com/nostra13/android-universal-image-loader 1. 功能介绍 1.1 Android Universal Image Loader Android Universal Image Loader 是一个强大的.可高度定制的图片缓存,本文简称为UIL. 简单的说 UIL 就做了一件事--获取图片并显示在相应的控件上. 1.2 基本使用 1.2.1 初始化 添加完依赖后在Application或Activity中初始化I

Android图片异步加载之Android-Universal-Image-Loader

将近一个月没有更新博客了,由于这段时间以来准备毕业论文等各种事务缠身,一直没有时间和精力沉下来继续学习和整理一些东西.最近刚刚恢复到正轨,正好这两天看了下Android上关于图片异步加载的开源项目,就顺便整理记录下来,作为这一个多月来博客的重新开火做饭吧.从今天起我会陆续恢复博客的更新,也希望大家继续支持. 今天要介绍的是Github上一个使用非常广泛的图片异步加载库Android-Universal-Image-Loader,该项目的功能十分强大,可以说是我见过的目前功能最全.性能最优的图片异

Android图片异步加载之Android-Universal-Image-Loader(转)

今天要介绍的是Github上一个使用非常广泛的图片异步加载库Android-Universal-Image-Loader,该项目的功能十分强大,可以说是我见过的目前功能最全.性能最优的图片异步加载解决方案.做Android的同学都知道,Android加载大量图片时,由于系统分配给图片加载的内存大小有限,所以,如果加载图片量非常大的话容易报OOM异常,关于这个异常已经有不少解决方案了,我就不赘述.下面就简要介绍下这个开源项目的主要功能和使用: 一.功能概要 多线程图片加载: 灵活更改ImageLo

Android图片异步加载

原:http://www.cnblogs.com/angeldevil/archive/2012/09/16/2687174.html 相关:https://github.com/nostra13/Android-Universal-Image-Loader 开发Android程序,一般情况下都会有两个操作,图片的异步加载与缓存,而图片的异步加载大都是从网络读取图片(还有生成本地图片缩略图等操作),为了减少网络操作,加快图片加载速度就需要对图片进行缓存,所以网上的好多图片异步加载方法都是与图片的

Android图片异步加载框架Android-Universal-Image-Loader

Android-Universal-Image-Loader是一个图片异步加载,缓存和显示的框架.这个框架已经被很多开发者所使用,是最常用的几个Android开源项目之一,主流的应用,随便反编译几个,都可以见到它的身影.淘宝,天猫,Facebook,京东商城等都用到了这个项目. 该项目的Github地址链接:https://github.com/nostra13/Android-Universal-Image-Loader 运行流程: 每一个图片的加载和显示任务都运行在独立的线程中,除非这个图片

Android-Universal-Image-Loader 图片异步加载类库的使用(超详细配置)

这个图片异步加载并缓存的类已经被很多开发者所使用,是最常用的几个开源库之一,主流的应用,随便反编译几个火的项目,都可以见到它的身影. 可是有的人并不知道如何去使用这库如何进行配置,网上查到的信息对于刚接触的人来说可能太少了,下面我就把我使用过程中所知道的写了下来,希望可以帮助自己和别人更深入了解这个库的使用和配置. GITHUB上的下载路径为:https://github.com/nostra13/Android-Universal-Image-Loader ,下载最新的库文件,并且导入到项目的