zoukankan      html  css  js  c++  java
  • Android之ListView优化(使用Lrucache,图片滑动时使用默认图片,停止时加载)

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


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

    public class MyApp extends Application{
        @Override
        public void onCreate() {
            super.onCreate();
            File f = new File(Environment.getExternalStorageDirectory()+"/TestSyncListView/pic/");
            if (!f.exists()) {
                f.mkdirs();
            }
        }
    }


    图像读取工具类:

    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 LooperThread extends 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();
    		}
    	}                
  • 相关阅读:
    题库重整
    计算几何练习题――直线交点
    An Easy Task
    简单排序
    IBM Minus One
    Binary Numbers
    去掉VS2010代码中文注释的红色下划线
    【转】Windows socket基础
    【STL】vector的insert方法详解
    window7下 cocos2dx android交叉编译环境部署小结
  • 原文地址:https://www.cnblogs.com/lee0oo0/p/2990457.html
Copyright © 2011-2022 走看看