关闭

加载大图的优化

196人阅读 评论(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
查看评论

Android大图加载内存优化(如何防止OutOfMemory)

第三方图片加载核心技术揭秘:揭秘ImagLoader或者Picasso等第三方开源库的核心:加载原理和缓存原理。
  • CJ_star
  • CJ_star
  • 2015-08-21 15:47
  • 2303

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

一、背景 最近做项目需要用到选择图片上传,类似于微信、微博那样的图片选择器,ContentResolver读取本地图片资源并用RecyclerView+Glide加载图片显示就搞定列表的显示,这个没什么大问题,重点是,点击图片进入大图浏览,比如你相册有几百张图片,也就意味着在ViewPager中需要...
  • hqiong208
  • hqiong208
  • 2016-12-28 16:51
  • 8040

CFRunloop 优化TableView加载高清大图UI卡顿问题。单独分批加载

TableView卡顿环境分析:        tableView加载过多的高清大图,Runloop不只处理iOS事件,渲染图形也是runloop处理的。       而渲染图形的UI操作必须在主线程中,不能开辟线程进行图形处...
  • ZY_FlyWay
  • ZY_FlyWay
  • 2017-06-08 16:50
  • 1336

RunLoop UITableViewCell加载高清大图的速度优化

RunLoop UITableViewCell加载高清大图的速度优化 2017-02-14 14:25 出处:清屏网 人气:73 评论(0) iOS开发中,UITableView的优化一直是一个老生常谈的问题,除了常用的预加载,缓存等方法以外,其实利用RunLoop 的循...
  • requestnslog
  • requestnslog
  • 2017-03-06 15:23
  • 248

Fresco加载图片优化

今天在使用应用时发现,应用居然崩溃了!一看监听器发现,当列表滚动到底部后内存达到了63M以上后必定崩溃,以前怎么就没崩溃呢?怪事了,但是内存这么大肯定是有问题的!还是得解决一下内存高的问题。 优化方法是: public static void displayImage(Uri uri, Simpl...
  • fwt336
  • fwt336
  • 2016-10-09 14:52
  • 812

Android图片加载优化--图片缓存

转载请注明出处:作者CJstar为什么要使用内存缓存 内存缓存: 内存缓存是指将已经赋值的对象保存在内存中,当再次使用的时候直接去内存读取,不再做重复的创建操作。 内存缓存的优势: 对象的重复使用,不再去创建对象,减少内存消耗,便于内存的集中管理。同时在需要读取数据库或者外存的时候,使用内存缓...
  • CJ_star
  • CJ_star
  • 2015-09-17 19:52
  • 1027

IOS 多个UIImageView 加载高清大图时内存管理

当我们在某一个View  多个UIImageView,且UIImageView都显示的是高清大图,就有可能出现内存警告的问题。如果第一次进入这个view,没有发生内存警告,当再次进入这个view,如果上一次的内存没有及时释放,这一次次的累加,便可导致内存崩溃。 1,UIImage 加载...
  • pzhtpf
  • pzhtpf
  • 2014-08-25 10:02
  • 14987

Android ImageView高效加载大图

ImageVIew高效加载大图
  • yang786654260
  • yang786654260
  • 2015-10-12 17:07
  • 1644

UIImage 加载性能优化

UIImage 存在 延迟解压的问题。这会占用时间。        一旦图片文件被加载就必须要进行解码,解码过程是一个相当复杂的任务,需要消耗非常长的时间。解码后的图片将同样使用相当大的内存。       ...
  • bravegogo
  • bravegogo
  • 2016-04-06 20:06
  • 1790

利用NSRunLoop优化大图加载

思路是把原来一次runloop完成的操作,放在多次runloop里完成。 别人写的例子 https://github.com/diwu/RunLoopWorkDistribution
  • ywg490043589
  • ywg490043589
  • 2016-11-02 15:27
  • 109
    个人资料
    • 访问:218968次
    • 积分:5542
    • 等级:
    • 排名:第5712名
    • 原创:326篇
    • 转载:192篇
    • 译文:1篇
    • 评论:15条
    文章分类