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

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

注意: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();
         }
     }
目录
相关文章
|
8月前
|
数据库 Android开发
Android使用EditText+Listview实现搜索效果(使用room模糊查询)
本文介绍如何在Android中使用EditText与ListView实现搜索功能,并结合Room数据库完成模糊查询。主要内容包括:Room的模糊查询语句(使用`||`代替`+`号)、布局美化(如去除ListView分割线和EditText下划线)、EditText回车事件监听,以及查询逻辑代码示例。此外,还提供了相关扩展文章链接,帮助读者深入了解ListView优化、动态搜索及Room基础操作。
563 65
|
3月前
|
移动开发 JavaScript 应用服务中间件
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
343 5
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
4月前
|
存储 消息中间件 人工智能
【08】AI辅助编程完整的安卓二次商业实战-修改消息聊天框背景色-触发聊天让程序异常终止bug牵涉更多聊天消息发送优化处理-优雅草卓伊凡
【08】AI辅助编程完整的安卓二次商业实战-修改消息聊天框背景色-触发聊天让程序异常终止bug牵涉更多聊天消息发送优化处理-优雅草卓伊凡
329 10
【08】AI辅助编程完整的安卓二次商业实战-修改消息聊天框背景色-触发聊天让程序异常终止bug牵涉更多聊天消息发送优化处理-优雅草卓伊凡
|
8月前
|
XML Android开发 数据格式
Android利用selector(选择器)实现图片动态点击效果
本文介绍了Android中ImageView的`src`与`background`属性的区别及应用,重点讲解如何通过设置背景选择器实现图片点击动态效果。`src`用于显示原图大小,不拉伸;`background`可随组件尺寸拉伸。通过创建`selector_setting.xml`,结合`setting_press.xml`和`setting_normal.xml`定义按下和正常状态的背景样式,提升用户体验。示例代码展示了具体实现步骤,包括XML配置和形状定义。
375 3
Android利用selector(选择器)实现图片动态点击效果
|
10月前
|
JavaScript Linux 网络安全
Termux安卓终端美化与开发实战:从下载到插件优化,小白也能玩转Linux
Termux是一款安卓平台上的开源终端模拟器,支持apt包管理、SSH连接及Python/Node.js/C++开发环境搭建,被誉为“手机上的Linux系统”。其特点包括零ROOT权限、跨平台开发和强大扩展性。本文详细介绍其安装准备、基础与高级环境配置、必备插件推荐、常见问题解决方法以及延伸学习资源,帮助用户充分利用Termux进行开发与学习。适用于Android 7+设备,原创内容转载请注明来源。
2582 77
|
8月前
|
Java Android开发
Android图片的手动放大缩小
本文介绍了通过缩放因子实现图片放大缩小的功能,效果如动图所示。关键步骤包括:1) 在布局文件中设置 `android:scaleType=&quot;matrix&quot;`;2) 实例化控件并用 `ScaleGestureDetector` 处理缩放手势;3) 使用 `Matrix` 对图片进行缩放处理。为避免内存崩溃,可在全局配置添加 `android:largeHeap=&quot;true&quot;`。代码中定义了 `beforeScale` 和 `nowScale` 变量控制缩放范围,确保流畅体验。
283 8
|
8月前
|
Java Android开发
Android使用okhttp加载图片
本教程介绍了如何使用 OkHttp 和 Handler 在 Android 应用中加载并显示网络图片。首先确保添加了网络权限和 OkHttp、Okio 的依赖包。通过定义全局 Handler 处理消息,实例化 OkHttpClient 请求图片数据,并在 onResponse 方法中将图片数据传递给主线程,最终利用 Bitmap 加载到 ImageView 中。
164 4
|
8月前
|
缓存 编解码 Android开发
Android内存优化之图片优化
本文主要探讨Android开发中的图片优化问题,包括图片优化的重要性、OOM错误的成因及解决方法、Android支持的图片格式及其特点。同时介绍了图片储存优化的三种方式:尺寸优化、质量压缩和内存重用,并详细讲解了相关的实现方法与属性。此外,还分析了图片加载优化策略,如异步加载、缓存机制、懒加载等,并结合多级缓存流程提升性能。最后对比了几大主流图片加载框架(Universal ImageLoader、Picasso、Glide、Fresco)的特点与适用场景,重点推荐Fresco在处理大图、动图时的优异表现。这些内容为开发者提供了全面的图片优化解决方案。
323 1
|
移动开发 监控 前端开发
构建高效Android应用:从优化布局到提升性能
【7月更文挑战第60天】在移动开发领域,一个流畅且响应迅速的应用程序是用户留存的关键。针对Android平台,开发者面临的挑战包括多样化的设备兼容性和性能优化。本文将深入探讨如何通过改进布局设计、内存管理和多线程处理来构建高效的Android应用。我们将剖析布局优化的细节,并讨论最新的Android性能提升策略,以帮助开发者创建更快速、更流畅的用户体验。
209 10
|
存储 缓存 编解码
Android经典面试题之图片Bitmap怎么做优化
本文介绍了图片相关的内存优化方法,包括分辨率适配、图片压缩与缓存。文中详细讲解了如何根据不同分辨率放置图片资源,避免图片拉伸变形;并通过示例代码展示了使用`BitmapFactory.Options`进行图片压缩的具体步骤。此外,还介绍了Glide等第三方库如何利用LRU算法实现高效图片缓存。
236 20
Android经典面试题之图片Bitmap怎么做优化