写这篇文章并不是教大家怎么样用listview异步加载图片,因为这样的文章在网上已经有很多了,比如这位仁兄写的就很好

http://www.iteye.com/topic/685986

我也是因为看了这篇文章而受到了启发。

先说说这篇文章的优点把,开启线程异步加载图片,然后刷新UI显示图片,而且通过弱引用缓存网络加载的图片,节省了再次连接网络的开销。

这样做无疑是非常可取的方法,但是加载图片时仍然会感觉到轻微的卡屏现象,特别是listview里的item在进行快速滑动的时候。

我找了一下原因,可能是在listview快速滑动屏幕的时候划过的item太多 而且每次调用getView方法后就会异步的在过去某个时间内用handler刷新一下UI,

如果在同一时间调用handler刷新UI次数多了就会造成这样的卡屏现象。

后来又一想,其实我们完全没有必要在listview正在滑动的时候去后台加载图片(不管这是图片是在缓存里还是在网络上),这样无疑造成了很大的资源浪费。

我们只需要在listview滑动停止之后再去加载listview里面显示的几个item里面的图片就好了。

根据以上想法,我做了一些设计改造:

1.在adapter 的 getview方法里面启动加载图片的thread,如果listview在滑动则wait

2.监听listview滑动停止事件,获得listview显示的item的最上面和最下面的序号,并唤醒所有加载图片的thread,判断加载图片的序号是否是在范围内,如果是则继续加载,如果不是则结束thread


部分代码如下:
@Overridepublic View getView(int position, View convertView, ViewGroup parent) {if(convertView == null){convertView = mInflater.inflate(R.layout.book_item_adapter, null);}BookModel model = mModels.get(position);convertView.setTag(position);ImageView iv = (ImageView) convertView.findViewById(R.id.sItemIcon);TextView sItemTitle =  (TextView) convertView.findViewById(R.id.sItemTitle);TextView sItemInfo =  (TextView) convertView.findViewById(R.id.sItemInfo);sItemTitle.setText(model.book_name);sItemInfo.setText(model.out_book_url);iv.setBackgroundResource(R.drawable.rc_item_bg);syncImageLoader.loadImage(position,model.out_book_pic,imageLoadListener);return  convertView;}SyncImageLoader.OnImageLoadListener imageLoadListener = new SyncImageLoader.OnImageLoadListener(){@Overridepublic void onImageLoad(Integer t, Drawable drawable) {//BookModel model = (BookModel) getItem(t);View view = mListView.findViewWithTag(t);if(view != null){ImageView iv = (ImageView) view.findViewById(R.id.sItemIcon);iv.setBackgroundDrawable(drawable);}}@Overridepublic void onError(Integer t) {BookModel model = (BookModel) getItem(t);View view = mListView.findViewWithTag(model);if(view != null){ImageView iv = (ImageView) view.findViewById(R.id.sItemIcon);iv.setBackgroundResource(R.drawable.rc_item_bg);}}};public void loadImage(){int start = mListView.getFirstVisiblePosition();int end =mListView.getLastVisiblePosition();if(end >= getCount()){end = getCount() -1;}syncImageLoader.setLoadLimit(start, end);syncImageLoader.unlock();}AbsListView.OnScrollListener onScrollListener = new AbsListView.OnScrollListener() {@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {switch (scrollState) {case AbsListView.OnScrollListener.SCROLL_STATE_FLING:DebugUtil.debug("SCROLL_STATE_FLING");syncImageLoader.lock();break;case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:DebugUtil.debug("SCROLL_STATE_IDLE");loadImage();//loadImage();break;case AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:syncImageLoader.lock();break;default:break;}}@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {// TODO Auto-generated method stub}};

Syncimageloader代码
import java.io.DataInputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.lang.ref.SoftReference;import java.net.URL;import java.util.HashMap;import android.graphics.drawable.Drawable;import android.os.Environment;import android.os.Handler;public class SyncImageLoader {private Object lock = new Object();private boolean mAllowLoad = true;private boolean firstLoad = true;private int mStartLoadLimit = 0;private int mStopLoadLimit = 0;final Handler handler = new Handler();private HashMap<String, SoftReference<Drawable>> imageCache = new HashMap<String, SoftReference<Drawable>>();   public interface OnImageLoadListener {public void onImageLoad(Integer t, Drawable drawable);public void onError(Integer t);}public void setLoadLimit(int startLoadLimit,int stopLoadLimit){if(startLoadLimit > stopLoadLimit){return;}mStartLoadLimit = startLoadLimit;mStopLoadLimit = stopLoadLimit;}public void restore(){mAllowLoad = true;firstLoad = true;}public void lock(){mAllowLoad = false;firstLoad = false;}public void unlock(){mAllowLoad = true;synchronized (lock) {lock.notifyAll();}}public void loadImage(Integer t, String imageUrl,OnImageLoadListener listener) {final OnImageLoadListener mListener = listener;final String mImageUrl = imageUrl;final Integer mt = t;new Thread(new Runnable() {@Overridepublic void run() {if(!mAllowLoad){DebugUtil.debug("prepare to load");synchronized (lock) {try {lock.wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}if(mAllowLoad && firstLoad){loadImage(mImageUrl, mt, mListener);}if(mAllowLoad && mt <= mStopLoadLimit && mt >= mStartLoadLimit){loadImage(mImageUrl, mt, mListener);}}}).start();}private void loadImage(final String mImageUrl,final Integer mt,final OnImageLoadListener mListener){if (imageCache.containsKey(mImageUrl)) {              SoftReference<Drawable> softReference = imageCache.get(mImageUrl);              final Drawable d = softReference.get();              if (d != null) {              handler.post(new Runnable() {    @Override    public void run() {    if(mAllowLoad){    mListener.onImageLoad(mt, d);    }    }    });                return;              }          }  try {final Drawable d = loadImageFromUrl(mImageUrl);if(d != null){                imageCache.put(mImageUrl, new SoftReference<Drawable>(d));}handler.post(new Runnable() {@Overridepublic void run() {if(mAllowLoad){mListener.onImageLoad(mt, d);}}});} catch (IOException e) {handler.post(new Runnable() {@Overridepublic void run() {mListener.onError(mt);}});e.printStackTrace();}}public static Drawable loadImageFromUrl(String url) throws IOException {DebugUtil.debug(url);if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){File f = new File(Environment.getExternalStorageDirectory()+"/TestSyncListView/"+MD5.getMD5(url));if(f.exists()){FileInputStream fis = new FileInputStream(f);Drawable d = Drawable.createFromStream(fis, "src");return d;}URL m = new URL(url);InputStream i = (InputStream) m.getContent();DataInputStream in = new DataInputStream(i);FileOutputStream out = new FileOutputStream(f);byte[] buffer = new byte[1024];int   byteread=0;while ((byteread = in.read(buffer)) != -1) {out.write(buffer, 0, byteread);}in.close();out.close();Drawable d = Drawable.createFromStream(i, "src");return loadImageFromUrl(url);}else{URL m = new URL(url);InputStream i = (InputStream) m.getContent();Drawable d = Drawable.createFromStream(i, "src");return d;}}}

为了让大家更好的理解,我添加了源代码例子,还特地美化了一下UI


源码下载:http://pan.baidu.com/share/link?shareid=2292453226&uk=454114200 原文地址: http://www.iteye.com/topic/1118828

更多相关文章

  1. Android(安卓)基于Zxing的扫码功能实现(二)
  2. Android(安卓)BroastCast的使用详解
  3. Android核心分析之一:分析方法论探讨之设计意图
  4. Android面试题整理(selfmade)——坚持每天回答一个
  5. Android(安卓)AlertDialog学习笔记
  6. 实现Unity和Android进行交互
  7. Android(安卓)2D画图类Path精炼详解
  8. android应用程序图片格式的选择
  9. Android(安卓)用户界面---菜单(Menus 一)

随机推荐

  1. 提供一些Android免费课程分享给大家
  2. Android(安卓)多国语言文件夹
  3. Android获取OAID设备标识
  4. Android(安卓)Gradle Plugin指南(三)——依
  5. Android消息机制之三---Message
  6. Android中ProgressDialog的简单示例
  7. Android(安卓)Studio添加aar依赖的两种方
  8. android project 文件夹
  9. 使用air进行移动app开发常见功能和问题(二
  10. 使用Android系统自带的icon图标