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();
         }
     }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值