ListView的异步加载图片问题与优化
2016-04-02 12:18
459 查看
本文通过AyncTask异步加载网络图片
参考:
http://blog.csdn.net/xiaanming/article/details/9825113
通过Thread异步加载位图
通过Header处理,在主线程刷新UI
通过为加载的网络图片设置Tag的方式解决。在为Item设置图片是先判断Tag是否正确,正确才进行加载。
在滑动时停止一切数据加载任务,当滑动停止后再次加载当前页的数据
Apater添加OnScrollListener接口
注册接口
在onScroll函数中获取当前页的Item的开始项与结束项,并判断如果是第一次启动则手动加载
onScrollStateChanged函数中判断当前状态:滑动状态时停止加载图片线程,停止状态时启动加载图片线程
代码ListAdapter中:
细节处理:
1. 定义String数组用来管理当前页面的URL,在loadImages中初始化它
定义一个集合,用于管理NewsAyncTask
private Set mTasks;
自定义关闭AyncTask函数
参考:
http://blog.csdn.net/xiaanming/article/details/9825113
1. ListView异步访问网络图片
1.通过Theard加载
通过Url获得位图public Bitmap getBitmapFromurl(String urlString) { Bitmap bitmap = null; BufferedInputStream is = null; URLConnection connection; try { URL url = new URL(urlString);//把一个string转化为Url connection = (URLConnection) url.openConnection();//通过url开启一个connection is = new BufferedInputStream(connection.getInputStream()); bitmap = BitmapFactory.decodeStream(is);//将isbuffer流数据转化为bitmap is.close(); } catch (IOException e) { e.printStackTrace(); } finally { } return bitmap; }
通过Thread异步加载位图
public void showImage(ImageView imageView, final String url) { new Thread() { @Override public void run() { super.run(); Bitmap bitmap = getBitmapFromurl(url); Message message = Message.obtain(); message.obj = bitmap; mHandler.sendMessage(message); } }.start(); }
通过Header处理,在主线程刷新UI
private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (mImageView.getTag().equals(url)) {//通过Tag防止图片错位 mImageView.setImageBitmap((Bitmap) msg.obj); } } };
2.通过AsyncTask加载
public void showImageByAsyncTask(ImageView imageView, String url) { Bitmap bitmap = getBitmapFromCache(url);//从缓存中读取位图 if (bitmap == null) { new NewsAsyncTask(url).execute(url);//网络加载图片 //imageView.setImageResource(R.drawable.ic_launcher);//加载默认图片 } else { imageView.setImageBitmap(bitmap); } } private class NewsAsyncTask extends AsyncTask<String, Void, Bitmap> { private String mUrl; public NewsAsyncTask(String url) { mUrl = url; } @Override protected Bitmap doInBackground(String... params) { mUrl = params[0]; Bitmap bitmap = getBitmapFromurl(mUrl); if (bitmap != null) { addBitmapToCache(mUrl, bitmap);//将bitmap添加进缓存 } return bitmap; } @Override protected void onPostExecute(Bitmap bitmap) { super.onPostExecute(bitmap); ImageView imageView = (ImageView) mListView.findViewWithTag(mUrl); if (imageView != null && bitmap != null) { imageView.setImageBitmap(bitmap); } mTasks.remove(this); } }
2. ListView异步加载网络图片的问题及其优化
1. 加载网络图片错位问题:
通过文艺方法重写listview的getView方法,因为listview缓存机制的存在,缓存池中始终保持三个Item布局,并在加载下一个时用到前面回收的Item,前面的Item以前加载的布局会在后面布局中先加载,然后通过访问网络重新刷新,因此会有图片错位的问题。通过为加载的网络图片设置Tag的方式解决。在为Item设置图片是先判断Tag是否正确,正确才进行加载。
2. 图片缓存机制
为了使加载过得图片不再重新加载,引进缓存机制来优化listview,这里使用的是LrucaChe1. 定义 public LruCache<String, Bitmap> myLruCache;//定义一个LruCache泛型 2. 在构造方法中初始化它 // 获取运行时最大缓存 int maxMemory = (int) Runtime.getRuntime().maxMemory(); // 设置LruCache可用的最大缓存 int cacheSize = maxMemory / 5; myLruCache = new LruCache<String, Bitmap>(cacheSize) { @Override protected int sizeOf(String url, Bitmap bitmap) { // 重写此方法用来衡量每张图片的大小,默认返回图片的数量 return bitmap.getByteCount(); } }; 3. 添加图片到缓存中 public void addBitmapToCache(String url, Bitmap bitmap) { if (getBitmapFromCache(url) == null) { myLruCache.put(url, bitmap); } } 4.从缓存中获取图片 public Bitmap getBitmapFromCache(String url) { return myLruCache.get(url); }
3. 滑动卡顿问题
在滑动时系统不停的加载网络图片然后刷新Item,频繁刷新UI容易使系统卡顿。在滑动时停止一切数据加载任务,当滑动停止后再次加载当前页的数据
Apater添加OnScrollListener接口
注册接口
在onScroll函数中获取当前页的Item的开始项与结束项,并判断如果是第一次启动则手动加载
onScrollStateChanged函数中判断当前状态:滑动状态时停止加载图片线程,停止状态时启动加载图片线程
代码ListAdapter中:
@Override public void onScrollStateChanged(AbsListView view, int scrollState) { if (scrollState == SCROLL_STATE_TOUCH_SCROLL) { // 停止加载图片 mImageload.cancelload(); } else if (scrollState == SCROLL_STATE_IDLE) { // 开始加载图片 mImageload.loadImages(mStart, mEnd); } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { mStart = firstVisibleItem; mEnd = firstVisibleItem + visibleItemCount; if (mFirst && visibleItemCount > 0) { mImageload.loadImages(mStart, mEnd); mFirst = false; } }
细节处理:
1. 定义String数组用来管理当前页面的URL,在loadImages中初始化它
public void loadImages(int start, int end) { for (int i = start; i < end; i++) { final String url = ListAdapter.URLS[i]; Bitmap bitmap = getBitmapFromCache(url); if (bitmap == null) { NewsAsyncTask task = new NewsAsyncTask(url); task.execute(url); mTasks.add(task);//将task加入集合,便于管理 } else { ImageView imageView = (ImageView) mListView .findViewWithTag(url); imageView.setImageBitmap(bitmap); } } }
定义一个集合,用于管理NewsAyncTask
private Set mTasks;
自定义关闭AyncTask函数
public void cancelload() { if (mTasks != null) { for (NewsAsyncTask task : mTasks) { task.cancel(false); } } }
相关文章推荐
- 完美实现Android ListView中的TextView的跑马灯效果
- android上改变listView的选中颜色
- 按右键另存图片只能存BMP
- photoshop去除图片上的水印
- ruby实现的一个异步文件下载HttpServer实例
- C#异步绑定数据实现方法
- Delphi7中Listview的常用功能汇总
- Delphi控件ListView的属性及使用方法详解
- upload上传单张图片
- 图片引发的溢出危机(图)
- 科学知识:同步、异步、阻塞和非阻塞区别
- 探讨Ajax中同步与异步之间的区别
- C#实现把彩色图片灰度化代码分享
- C#将图片和字节流互相转换并显示到页面上
- C#监控文件夹并自动给图片文件打水印的方法
- 纯CSS实现的当鼠标移上图片添加阴影效果代码
- 如何使用C#从word文档中提取图片
- C#中异步回调函数用法实例
- C#实现打开画图的同时载入图片、最大化显示画图窗体的方法
- C#图片添加水印的实现代码