android使用LruCache对listview加载图片时候优化处理

时间:2021-11-09 21:13:47

注意:LruCache是有版本限制的,低版本的sdk需要在libs文件夹添加相应的support-4v文件。
本文改造的大部分是参考http://www.iteye.com/topic/1118828,感谢。
不废话直接上工程代码,内有关键注释,项目就不上传了,自己对照着上面网址改呗。


首先是Application文件,负责创建图片存储文件夹:

android使用LruCache对listview加载图片时候优化处理
public class MyApp extends Application{
@Override
public void onCreate() {
super.onCreate();
File f
= new File(Environment.getExternalStorageDirectory()+"/TestSyncListView/pic/");
if (!f.exists()) {
f.mkdirs();
}
}
}
android使用LruCache对listview加载图片时候优化处理


图像读取工具类:

?
public class SyncImageLoaderUtil {    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>>(); 
       private LruCache<String,Bitmap> mMemoryCache;         RunInOtherThread runInOutherThread;         public SyncImageLoaderUtil(Context context) {          super();                  int memClass = ((ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();        int cacheSize = 1024 *1024 *memClass / 8;        mMemoryCache = new LruCache<String, Bitmap>(cacheSize){            @Override            protected int sizeOf(String key, Bitmap value) {                // TODO Auto-generated method stub                return value.getRowBytes();            }        };                 runInOutherThread = new RunInOtherThread();         runInOutherThread.start();            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) {  //         
LogUtil.i("test", 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;                     runInOutherThread.getHandler().post(new Runnable() {                 @Override             public void run() {                  if (!mAllowLoad) {                      synchronized (lock) {                          try                             lock.wait();                         }catch (InterruptedException e) {                              // TODO Auto-generated catch block                              e.printStackTrace();                                                                                                if (mAllowLoad && firstLoad) {                      loadImage(mImageUrl, mt, mListener);                     //               
LogUtil.e("test", "原始开始:"+mStartLoadLimit+"原始当前位置:"+mt+"原始结束:"+mStopLoadLimit);
                if (mAllowLoad && mt <= mStopLoadLimit && mt >= mStartLoadLimit) {  //                 
LogUtil.e("test", "开始:"+mStartLoadLimit+"当前位置:"+mt+"结束:"+mStopLoadLimit);
                    loadImage(mImageUrl, mt, mListener);                                       });                private void loadImage(final String mImageUrl, final Integer mt,              final OnImageLoadListener mListener) {             if (mImageUrl!=null && mMemoryCache.get(mImageUrl)!=null) {  //           
SoftReference<Drawable> softReference = imageCache.get(mImageUrl); 
            final Drawable d = new BitmapDrawable(mMemoryCache.get(mImageUrl)); //           
LogUtil.d("ppp", "drawable:"+d);
            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) {                  mMemoryCache.put(mImageUrl, ((BitmapDrawable)d).getBitmap());                        handler.post(new Runnable() {                  @Override                 public void run() {                      if (mAllowLoad) {                          mListener.onImageLoad(mt, d);                                                  });         }catch (IOException e) {              handler.post(new Runnable() {                  @Override                 public 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()                     +"/Weiyu/pic/" + MD5Util.getMD5(url.getBytes()));              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();            return loadImageFromUrl(url);         }else             URL m = new URL(url);             InputStream i = (InputStream) m.getContent();              Drawable d = Drawable.createFromStream(i, "src");             return d;                }

  
线程辅助类:

?
public class RunInOtherThread {    private static final String LOG_TAG = "RunInOtherThread"         private LooperThread localThread = new LooperThread();            private boolean isRunning = true       public Handler getHandler(){          return localThread.getHandler();                private class LooperThreadextends Thread {          private Handler mHandler;             public void run() {              Looper.prepare();             mHandler = new Handler() {                  public void handleMessage(Message msg) {                      onReceiveMessage(msg.what);                             };             Looper.loop();                            Handler getHandler(){              return mHandler;                              public void start(){         localThread.start();                public void quit(){         localThread.getHandler().getLooper().quit();                public void sendMessage(int what){         getHandler().sendEmptyMessage(what);                public Thread getThread(){          return localThread;                public void onReceiveMessage(int what){};}

  
使用类:

? //
实例化工具类
SyncImageLoaderUtil
syncImageLoader =
new SyncImageLoaderUtil(mContext);
 syncImageLoader.loadImage(position,
model.mPic, imageLoadListener);
//应用接口:参数一是加载图片的位置;参数二是加载的ImageView;参数三是回调接口
 //
map保存的键是位置,值是listview对应位置的布局
HashMap
map =
new HashMap();
map.put(position,
convertView);
 SyncImageLoaderUtil.OnImageLoadListener
imageLoadListener =
new SyncImageLoaderUtil.OnImageLoadListener() {
         @Override        public void onImageLoad(Integer t, Drawable drawable) {            View view = (View) map.get(t);            if (view != null) {                ImageView iv = (ImageView) view.findViewById(R.id.image);                iv.setBackgroundDrawable(drawable);            }        }         @Override        public void onError(Integer t) {                        // 图片加载失败                       // 取得listview对应的位置的行的内容布局                    MusicModel model = (MusicModel) getItem(t);            View view = mListView.findViewWithTag(model);            if (view != null) {                ImageView iv = (ImageView) view.findViewById(R.id.image);                iv.setBackgroundResource(R.drawable.img_pic);            }        }     };  //
实现类而且需要实现OnScrollListener接口
public void loadImage() {                // 不要在这里使用listview的getFirstVisiblePosition方法,位置不准        if (end >= getCount()) {            end = getCount() - 1;        }        syncImageLoader.setLoadLimit(start, end);        syncImageLoader.unlock();    }     @Override    public void onScrollStateChanged(AbsListView view, int scrollState) {        // TODO Auto-generated method stub        if (lodingView) {            switch (scrollState) {            case AbsListView.OnScrollListener.SCROLL_STATE_FLING:                syncImageLoader.lock();                break;            case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:                 loadImage();                break;            case AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:                syncImageLoader.lock();                break;            default:                break;            }        }    }     @Override    public void onScroll(AbsListView view, int firstVisibleItem,            int visibleItemCount,int totalItemCount) {        // 在这里取得的位置较准确,不过也会出现特殊的奇疤机型是不行的                // start与end是定义的变量        start = firstVisibleItem;        end = firstVisibleItem + visibleItemCount;        if (firstVisibleItem != 0) {                        // lodingView是控制变量,用来控制第一次进来视图加载读取图片            lodingView = true;        }else {            lodingView = false;            loadImage();        }    }