简单的ListView中item图片异步加载
2015-07-08 23:12
344 查看
前言:
在android开发当中,从目标地址获取图片往往都是采用异步加载的方法。当完全加载完图片后在进行显示,也有些是直接将加载的图片一点一点的显示出来。
这两个区别只是对流的处理不同而已。现在就讲讲当图片被完全获取到后在显示的方法。
一,效果图:
初始化: 获取后:
1.1,效果思路:
初始化的时候默认ImageView显示一张白色的图片,在加载完图片以后,用心的图片将白色图片给替换掉,就达到效果了。
二,代码实现:
主要类介绍:
AsyncImageLoadAdapter :ListView的自定义Adapter
AsyncLoad :图片异步加载类
MainActivity :主Activity。
相关的布局文件就不介绍了,在后面看就行了。
MainActivity:
这个MainActivity挺简单的,就是初始化相关控件,然后给ListView附上值而已。
AsyncImageLoadAdapter :
这个Adapter中加载了一个list_item布局(adapter中未用ViewHolder,不要去纠结这个,加上也可),来初始化未加载图片的时候。主要要说的是这段代码
这段代码就进行了异步去加载图片。
思路是:先将ListView中的每个item设置一个Tag,便于后面找到对应的item中imageView进行图片更新。
然后利用图片加载类去网络获取图片,获取到图片后采用接口回调的方式传回图片进行ImageView更新(UI线程中
执行的)
AsyncLoad:
[b] [/b]
要想更新界面上内容,就必须在UI线程中去更新,所以就采用handler.post方法,post里面Runnable中
run执行的代码其实是在UI线程中执行的,所以就符合android的规矩,才能进行更新
参考文章:http://blog.csdn.net/harvic880925/article/details/17766027#t7
源码下载:下载
在android开发当中,从目标地址获取图片往往都是采用异步加载的方法。当完全加载完图片后在进行显示,也有些是直接将加载的图片一点一点的显示出来。
这两个区别只是对流的处理不同而已。现在就讲讲当图片被完全获取到后在显示的方法。
一,效果图:
初始化: 获取后:
1.1,效果思路:
初始化的时候默认ImageView显示一张白色的图片,在加载完图片以后,用心的图片将白色图片给替换掉,就达到效果了。
二,代码实现:
主要类介绍:
AsyncImageLoadAdapter :ListView的自定义Adapter
AsyncLoad :图片异步加载类
MainActivity :主Activity。
相关的布局文件就不介绍了,在后面看就行了。
MainActivity:
public class MainActivity extends Activity { private ListView listView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initData(); } private void initView() { listView = (ListView) findView(R.id.listView); } private void initData() { List<HashMap<String, Object>> list = new ArrayList<HashMap<String, Object>>(); HashMap<String, Object> map1 = new HashMap<String, Object>(); map1.put("img", "http://img5.imgtn.bdimg.com/it/u=747474479,3247936386&fm=21&gp=0.jpg"); map1.put("txt", "条目一"); HashMap<String, Object> map2 = new HashMap<String, Object>(); map2.put("img", "http://pic.nipic.com/2007-12-22/2007122215556437_2.jpg"); map2.put("txt", "条目二"); HashMap<String, Object> map3 = new HashMap<String, Object>(); map3.put("img", "http://img1.imgtn.bdimg.com/it/u=1774561363,2410491846&fm=21&gp=0.jpg"); map3.put("txt", "条目三"); HashMap<String, Object> map4 = new HashMap<String, Object>(); map4.put("img", "http://img5.imgtn.bdimg.com/it/u=112049007,3368205326&fm=21&gp=0.jpg"); map4.put("txt", "条目四"); HashMap<String, Object> map5 = new HashMap<String, Object>(); map5.put("img", "http://img3.imgtn.bdimg.com/it/u=2953608063,4260501712&fm=21&gp=0.jpg"); map5.put("txt", "条目五"); list.add(map1); list.add(map2); list.add(map3); list.add(map4); list.add(map5); AsyncImageLoadAdapter adapter = new AsyncImageLoadAdapter( MainActivity.this, list, listView); listView.setAdapter(adapter); } private <T> T findView(int id) { return (T) findViewById(id); } }
这个MainActivity挺简单的,就是初始化相关控件,然后给ListView附上值而已。
AsyncImageLoadAdapter :
public class AsyncImageLoadAdapter extends BaseAdapter { private Context context; private List<HashMap<String, Object>> listData; private AsyncLoad asyncLoad; private ListView listView; public AsyncImageLoadAdapter(Context context1, List<HashMap<String, Object>> listData1, ListView listView1) { this.context = context1; this.listData = listData1; this.asyncLoad = AsyncLoad.instance(); this.listView = listView1; } @Override public int getCount() { return listData.size(); } @Override public Object getItem(int position) { return listData.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = LayoutInflater.from(context).inflate( R.layout.list_item, null); } convertView.setTag(position); ImageView imageView = (ImageView) convertView .findViewById(R.id.list_item_img); imageView.setBackgroundResource(R.drawable.img_black); TextView textView = (TextView) convertView .findViewById(R.id.list_item_tv); textView.setText("我是条目" + position); HashMap<String, Object> item = listData.get(position); String imageStr = (String) item.get("img"); asyncLoad.loadImage(position, imageStr, new ILoadListener() { @SuppressLint("NewApi") @Override public void onSuccess(Integer pos, Drawable drawable) { View view = listView.findViewWithTag(pos); if (view != null) { ImageView img = (ImageView) view .findViewById(R.id.list_item_img); img.setBackground(drawable); } } @Override public void onFail(String failStr) { Toast.makeText(context, "错误信息是->" + failStr, Toast.LENGTH_SHORT) .show(); } }); return convertView; } }
这个Adapter中加载了一个list_item布局(adapter中未用ViewHolder,不要去纠结这个,加上也可),来初始化未加载图片的时候。主要要说的是这段代码
asyncLoad.loadImage(position, imageStr, new ILoadListener() { @SuppressLint("NewApi") @Override public void onSuccess(Integer pos, Drawable drawable) { View view = listView.findViewWithTag(pos); if (view != null) { ImageView img = (ImageView) view .findViewById(R.id.list_item_img); img.setBackground(drawable); } } @Override public void onFail(String failStr) { Toast.makeText(context, "错误信息是->" + failStr, Toast.LENGTH_SHORT) .show(); } });
这段代码就进行了异步去加载图片。
思路是:先将ListView中的每个item设置一个Tag,便于后面找到对应的item中imageView进行图片更新。
然后利用图片加载类去网络获取图片,获取到图片后采用接口回调的方式传回图片进行ImageView更新(UI线程中
执行的)
AsyncLoad:
[b] [/b]
public class AsyncLoad { private static AsyncLoad asyncLoad; /** * 图片缓存容器,采用软引用,当用户手机内存不够时候,系统自动回收其所占有的内存 */ private HashMap<String, SoftReference<Drawable>> dataMap; /** * 用于在UI线程中进行UI更新 */ private Handler handler = new Handler(); public synchronized static AsyncLoad instance() { if (asyncLoad == null) asyncLoad = new AsyncLoad(); return asyncLoad; } public AsyncLoad() { dataMap = new HashMap<String, SoftReference<Drawable>>(); } // 内部接口对图片获取的监听 interface ILoadListener { /** * 图片加载成功后 * * @param pos * 对listView中pos位置 * @param drawable * 网络加载后获取到的图片 */ public void onSuccess(Integer pos, Drawable drawable); public void onFail(String failStr); } /** * 开启线程对图片进行加载 * * @param pos * listView的pos位置进行加载 * @param imageStr * 图片地址 * @param listener * 监听接口 */ public void loadImage(final Integer pos, final String imageStr, final ILoadListener listener) { // 开启一个线程获取图片资源 new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } load(pos, imageStr, listener); } }).start(); } private void load(final Integer pos, final String imageStr, final ILoadListener listener) { if (dataMap.containsKey(imageStr)) { SoftReference<Drawable> softReference = dataMap.get(imageStr); final Drawable d = softReference.get(); if (d != null) { handler.post(new Runnable() { @Override public void run() { listener.onSuccess(pos, d); } }); } return; } try { final Drawable d = loadImgFromUrl(imageStr); if (d != null) { SoftReference<Drawable> soft = new SoftReference<Drawable>(d); dataMap.put(imageStr, soft); } handler.post(new Runnable() { @Override public void run() { listener.onSuccess(pos, d); } }); } catch (final IOException e) { e.printStackTrace(); // 进行错误信息回报 handler.post(new Runnable() { @Override public void run() { listener.onFail(e.getMessage()); } }); } } /** * 获取网路图片资源 * * @param url * @return * @throws IOException */ private static Drawable loadImgFromUrl(String urlStr) throws IOException { System.out.println("urlStr->" + urlStr); URL url; InputStream i = null; url = new URL(urlStr); i = (InputStream) url.getContent(); Drawable drawable = Drawable.createFromStream(i, "img"); return drawable; } }
要想更新界面上内容,就必须在UI线程中去更新,所以就采用handler.post方法,post里面Runnable中
run执行的代码其实是在UI线程中执行的,所以就符合android的规矩,才能进行更新
参考文章:http://blog.csdn.net/harvic880925/article/details/17766027#t7
源码下载:下载
相关文章推荐
- Codeforces Round #289 (Div. 2, ACM ICPC Rules) F. Progress Monitoring 区间dp
- iOS8 UILocalNotification 增加启动授权
- iOS8 UILocalNotification 增加启动授权
- Android DiskLruCache完全解析
- Csharp学习第三天
- [学习笔记—Objective-C]《Objective-C 程序设计 第6版》第十五章 数字 字符串和集合
- rm -rf惹的祸,未雨绸缪,防止数据丢失
- 二叉树的顺序结构
- for循环语句之兔子生崽
- LVS基础详解和NAT/DR模型的实现
- 运用指针复制的方法,输出用户自定义输入的字符串
- 【优秀网址汇总】
- intent常见应用
- 关于XML文档pull解析的新思考-内省的应用
- 缓存雪崩现象
- AFNetworking2.0源码解析
- automake自动生成Makefile及遇到的问题
- tcp协议的那些事
- 欢迎使用CSDN-markdown编辑器
- RTSP - RTP over TCP