关闭

加载大图的优化

124人阅读 评论(0) 收藏 举报
分类:
1、压缩图片;
2、LruCache缓存;
一、压缩图片
先介绍下图片质量(Bitmap.Config),一共有4种:
ALPHA_8 只有透明度,没有颜色,那么一个像素点占8位。
RGB_565 即R=5,G=6,B=5,没有透明度,那么一个像素点占5+6+5=16位。
ARGB_4444 由4个4位组成,即A=4,R=4,G=4,B=4,那么一个像素点占16位。
ARGB_8888 由4个8位组成,即A=8,R=8,G=8,B=8,那么一个像素点占32位。
默认是ARGB_8888。

据此我们可以写出如下函数:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //根据图片质量确定每个像素点所占字节数  
  2. public static int getBytesPerPixel(Bitmap.Config config) {    
  3.     if (config == Bitmap.Config.ARGB_8888) {    
  4.         return 4;    
  5.     } else if (config == Bitmap.Config.RGB_565) {    
  6.         return 2;    
  7.     } else if (config == Bitmap.Config.ARGB_4444) {    
  8.         return 2;    
  9.     } else if (config == Bitmap.Config.ALPHA_8) {    
  10.         return 1;    
  11.     }   
  12.     return 1;    
  13. }  

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //根据Bitmap的宽高来计算其大小,知道图片大小后,我们可以决定是否对其压缩  
  2. public static long getBitmapSizeInMemory(int imageW, int imageH) {  
  3.     return imageH * imageW * getBytesPerPixel(Bitmap.Config.ARGB_8888);    
  4. }  
BitmapFactory.Options有个inJustDecodeBounds属性,将inJustDecodeBounds设置为true时,就不解码图片到内存,只读取图片的基本信息,读取并设置之后,再把该值改为false,然后再进行解码获取图片,这就是压缩图片的原理。
代码如下:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //获取的inSampleSize必须是2的倍数 ps:本函数(getScaleInSampleSize)只是一种参考,具体实现还需要根据实际情况有所变动  
  2. public static int getScaleInSampleSize(int resW, int resH, int desW, int desH) {    
  3.     int scaleW = resW / desW;    
  4.     int scaleH = resH / desH;    
  5.     int largeScale = scaleH > scaleW ? scaleH : scaleW;    
  6.     int sampleSize = 1;    
  7.     while (sampleSize < largeScale) {    
  8.         sampleSize *= 2;    
  9.     }  
  10.     return sampleSize;    
  11. }  
  12. //获取压缩图片  
  13. public static Bitmap decodeBitmapFromResource(Resources res, int resId,    
  14.         int reqWidth, int reqHeight) {    
  15.     // 第一次解析将inJustDecodeBounds设置为true,来获取图片信息  
  16.     final BitmapFactory.Options options = new BitmapFactory.Options();    
  17.     options.inJustDecodeBounds = true;  
  18.     BitmapFactory.decodeResource(res, resId, options);    
  19.     int height = options.outHeight;    
  20.     int width = options.outWidth;    
  21.     String mimeType = options.outMimeType;   
  22.     // 调用上面定义的方法计算inSampleSize值    
  23.     options.inSampleSize = getScaleInSampleSize(width, height, reqWidth, reqHeight);    
  24.     //options.inPreferredConfig= Bitmap.Config.RGB_565; //如有必要,还可以修改图片质量,进一步减小图片大小  
  25.     // 使用获取到的inSampleSize值再次解析图片    
  26.     options.inJustDecodeBounds = false;    
  27.     return BitmapFactory.decodeResource(res, resId, options);    
  28. }  
二、使用LruCache缓存

LruCache缓存主要算法原理是把最近使用的对象用强引用存储在 LinkedHashMap 中,并且把最近最少使用的对象在缓存值即将达到预设定值之前从内存中移除。

用法如下:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. private LruCache<String, Bitmap> mMemoryCache;  
  2. @Override  
  3. protected void onCreate(Bundle savedInstanceState) {  
  4.     // 获取到可用内存的最大值,使用内存超出这个值会引起OutOfMemory异常。  
  5.     // LruCache通过构造函数传入缓存值,以KB为单位。  
  6.     int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);  
  7.     // 使用最大可用内存值的1/6作为缓存的大小。  
  8.     int cacheSize = maxMemory / 6;  
  9.     mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {  
  10.         @Override  
  11.         protected int sizeOf(String key, Bitmap bitmap) {  
  12.             // 重写此方法来衡量每张图片的大小,默认返回图片数量。  
  13.             return bitmap.getByteCount() / 1024;  
  14.         }  
  15.     };  
  16. }  
  17. public void addBitmapToMemoryCache(String key, Bitmap bitmap) {  
  18.     if (getBitmapFromMemCache(key) == null) {  
  19.         mMemoryCache.put(key, bitmap);  
  20.     }  
  21. }  
  22. public Bitmap getBitmapFromMemCache(String key) {  
  23.     return mMemoryCache.get(key);  
  24. }  
  25. public void loadBitmap(int resId, ImageView imageView) {  
  26.     final String imageKey = String.valueOf(resId);  
  27.     final Bitmap bitmap = getBitmapFromMemCache(imageKey);  
  28.     if (bitmap != null) {  
  29.         imageView.setImageBitmap(bitmap);  
  30.     } else {  
  31.         //如果缓存里面没有就使用默认的图片  
  32.         imageView.setImageResource(R.drawable.image_default);  
  33.         LoadWorkerTask task = new LoadWorkerTask();  
  34.         task.execute(resId);  
  35.     }  
  36. }  
  37. class LoadWorkerTask extends AsyncTask<Integer, Void, Bitmap> {  
  38.     // 在后台加载图片。  
  39.     @Override  
  40.     protected Bitmap doInBackground(Integer... params) {  
  41.         final Bitmap bitmap = decodeBitmapFromResource(  
  42.                 getResources(), params[0], 100100);  
  43.         addBitmapToMemoryCache(String.valueOf(params[0]), bitmap);  
  44.         return bitmap;  
  45.     }  
  46. }  
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:131335次
    • 积分:3966
    • 等级:
    • 排名:第7922名
    • 原创:249篇
    • 转载:169篇
    • 译文:1篇
    • 评论:7条
    文章分类
    新浪微博
    最新评论