您当前的位置: 首页 > 

xiangzhihong8

暂无认证

  • 4浏览

    0关注

    1324博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

大量图片优化

xiangzhihong8 发布时间:2014-11-04 17:54:27 ,浏览量:4

http://blog.csdn.net/yifei1989/article/details/19906821

最近在练习中用GridView加入相册中图片发现加入大量的相片之后,GirdView会变得很卡,想到或许可以用异步加载的方式来解决,但是能力有限,想得到却无法实现。在读了一些大牛的博客和代码之后,终于实现了。

1  在异步加载之前的代码的和普通加载代码一样,只需要在GirdView的Adapter的public View getView(int position, View convertView, ViewGroupparent)方法使用异步加载的方式返回ImageView。

2  如果能把加载过的图片给缓存起来,而不用每次都从sd卡上读取,这样效率应该会提高不少。所以可以先建一个缓存类,MemoryCache,为了能尽可能缓存,又尽可能的不抛出OOM的异常,可以使用SoftReference,软引用来缓冲图片。MemoryCache类的代码如下:

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 缓存类(图片的路径和图片) 
  3.  */  
  4. public class MemoryCache {  
  5.     private HashMap cache=new HashMap();  
  6.     //获取缓存图片  
  7.     public Bitmap get(String path) {  
  8.         if(cache.get(path)==null){  
  9.             return null;  
  10.         }else{  
  11.             return cache.get(path).get();  
  12.         }  
  13.     }  
  14.       
  15.     //新增缓存  
  16.     public void put(String url,Bitmap bitmap) {  
  17.         cache.put(url, new SoftReference(bitmap));  
  18.     }  
  19.       
  20.     //清空缓存  
  21.     public void clear() {  
  22.         cache.clear();  
  23.     }  
  24. }  

3  弄完了缓存类,接下来就可以弄异步加载的类,这个类主要在维护一个Stack,每次向这个类请求一个ImageView时,就要传入对应ImageView和图片的路径。异步类首先会根据图片的路径先去缓存中查找是否有缓存对应的BItMap,如果有就把他放到ImageView返回,如果没有就把这个ImageView和图片路径放到Stack中,并唤醒加载图片的线程。而加载图片的线程(线程优先权低于UI线程),会无限循环查看Stack大小,如果为0,就进入等待。如果不为0,就依次出栈Stack中的元素进行处理。(感觉像生产者-消费者模式)。

3.1 接下来,就写这个异步类的变量和构造函数了:

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. private MemoryCache cache;  
  2.     private PhotosStack photosStack;  
  3.     private LoadImageThread loadImageThread;  
  4.     //用来保存每个月ImageView和对应应加载的图片  
  5.     private Map viewPath=Collections.synchronizedMap(new HashMap());  
  6.     public LoadImage(Activity activity) {  
  7.         super();  
  8.         cache=new MemoryCache();  
  9.         photosStack=new PhotosStack();  
  10.         loadImageThread=new LoadImageThread(activity);  
  11.         //设置异步加载线程优先权低于UI线程  
  12.         loadImageThread.setPriority(Thread.NORM_PRIORITY);  
  13.     }  

其中MemoryCache是缓存类,PhotosStack类中维护一个Stack,LoadImageThread类是负责异步加载图片的。而viewPath这个变量是为了要保证GridView对应Position放对应的ImageView,如果没有这个变量,GridView中排列就会无序,在处理GridView的点击事件时候,就不好处理。而对viewPath的操作的异步,所以就需要线程安全咯。

PhotosStack代码如下:

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. //维护需要被填充的Image和对应图片路径的栈  
  2. class PhotosStack{  
  3.     Stack stack=new Stack();  
  4.     //移除指定ImageView  
  5.     public void remove(ImageView iView) {  
  6.         for(int i=0;i0){  
  7.                         final MyPhoto photo;  
  8.                         //得到栈顶的MyPhoto  
  9.                         synchronized (photosStack.stack) {  
  10.                              photo= photosStack.stack.pop();  
  11.                         }   
  12.                         cache.put(photo.path,getSmallBitmap(photo.path) );  
  13.                         String ivPathString=viewPath.get(photo.imageView);  
  14.                         if(ivPathString!=null&& ivPathString.equalsIgnoreCase(photo.path)){  
  15.                             Runnable runableRunnable=new Runnable() {  
  16.                                 @Override  
  17.                                 public void run() {  
  18.                                     photo.imageView.setImageBitmap(getSmallBitmap(photo.path));  
  19.                                 }  
  20.                             };  
  21.                             activity.runOnUiThread(runableRunnable);  
  22.                         }  
  23.                     }  
  24.                     if(photosStack.stack.size()==0){  
  25.                         synchronized (photosStack.stack) {  
  26.                             photosStack.stack.wait();  
  27.                         }  
  28.                     }  
  29.                 } catch (InterruptedException e) {  
  30.                     // TODO 自动生成的 catch 块  
  31.                     e.printStackTrace();  
  32.                 }  
  33.             }  
  34.         }  
  35.     }  
  36.       

其中缩小图片方法getSmallBitmap(String path),代码如下:

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. //缩小图片  
  2.     public Bitmap getSmallBitmap(String path) {  
  3.         Options options=new Options();  
  4.         options.inJustDecodeBounds=true;  
  5.         BitmapFactory.decodeFile(path,options);  
  6.         int REQUIRE_SIZE=80;  
  7.         int scare=1;  
  8.           
  9.         while(true){  
  10.             if(options.outWidth
关注
打赏
1482932726
查看更多评论
立即登录/注册

微信扫码登录

0.0712s