加载大图的优化

原创 2016年08月31日 09:46:25
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. }  
版权声明:本文为博主原创文章,未经博主允许不得转载。

ios加载大图

  • 2014年04月29日 17:58
  • 7.95MB
  • 下载

Android_性能优化之ViewPager加载成百上千高清大图oom解决方案

转载至:点击打开链接 一、背景 最近做项目需要用到选择图片上传,类似于微信、微博那样的图片选择器,ContentResolver读取本地图片资源并用RecyclerView+Glide...

Android_优化查询加载大数量的本地相册图片

转自:http://www.2cto.com/kf/201607/527863.html 一、概述 讲解优化查询相册图片之前,我们先来看下PM提出的需求,PM的需求很简单,就是要做...

android图片加载内存优化方法,有效解决大图片内存溢出(oom)

低内存的手机如果直接加载大图片,往往会出现OOM的情况.即便是主流手机,也不能无限制的加载大图片.所以在显示图片之前,需要对图片处理,把图片缩放为最合适的尺寸再显示. 网上很大方法都是不管三七二十一,...

网页优化 CSS Sprites 背景图 一次加载

对于访问者来说,网站的页面能够即时的呈现出来,无疑是让人感到很愉快的一件事;而相反的是如果网页打开速度很慢的话,无疑这个网站将损失很多的用户。据许多研究表明:用户最满意的打开网页时间,是在2秒以下;用...

Android加载大图的优化策略

当我们使用大的Bitmap图片时很容易出现OOM的现象,今天我们就来看下该怎么解决这个问题。 一般有两种方法: 1、压缩图片; 2、LruCache缓存; 当然这两种方式同时使用效果更好^^ ...

Android 性能优化(十)图片加载和大图片缓存机制OOM完美解决方案LruCache&DiskLruCache

主要的三种方式:图片缩放节约内存,内存缓存,硬盘缓存 一.inSampleSize(缩放值) 经过研究,发现,Options中有个属性inJustDecodeBounds,研究了一下,终于...

[Android实例] Android有效解决加载大图片内存溢出问题及优化虚拟机内存

本文转自:http://www.qianxk.com/forum.php?mod=viewthread&tid=9514 尽量不要使用setImageBitmap或setImageResou...
  • jddkdd2
  • jddkdd2
  • 2012年08月16日 09:56
  • 478

Bitmap加载大图优化之位图重采样与Bitmap缓存Lru算法分析

为什么要优化Bitmap     安卓加载图片一般会用到ImageView控件,然后用setImageBitmap()、setImageResource()等方法指定要显示的图片,这些方法最终都会调用...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:加载大图的优化
举报原因:
原因补充:

(最多只允许输入30个字)