2019独角兽企业重金招聘Python工程师标准>>>

最近做了个资讯类的app项目,涉及到大量的图片加载,因公司项目框架已经集成了Glide用于加载图片,理所当然就直接用了Glide来加载app中的图片。原本以为用了Glide第三方框架就可以高枕无忧了,然并卵,一发包测试,测试反馈部分图片无法加载,各种OOM。然而自己测试却没有任何问题,此刻我的内心是崩溃的。一问细节,测试机型版本4.0,RAM1GB。开发调试时,机型的配置是市面上主流及较高的配置,所以一点问题都察觉不到。没有办法,谁让合同上签的最低兼容版本是4.0呢?只能做适配了。

一、OOM的原因

OOM:所谓的OOM指的就是Out-of-Memory内存不足啦。Android上加载图片OOM无非也就那么几个。

1、Bitmap用完没有回收,导致内存泄漏。
2、手机像素越来越高,照片体积越来越大,在上传及加载时如不进行压缩处理,OOM是常有的事。
3、机型偏旧、内存偏小。近几年Android的发力生猛,机型配置虽然一路飙升,但是仍然有一部分人还在用着两年前的机器。作为app的厂商又不能放弃这一部分用户。无奈,开发时还是得根据机型做适配。

二、解决方案

  • 首选当然还是得选择第三方图片加载库,主流的加载库无非是UniversalImageLoader、Fresco、Glide、Picasso,推荐Glide。
  • 按照界面图片尺寸,加载不同尺寸的图片
  • LruCache 缓存工具类

要实现图片加载最优,单单靠以上某一种方式处理肯定是不靠谱的,所以我们要使用的是三者结合来处理。是的,你没有听错。

三、分析原由

1.市面上主流的图片加载开源库,在磁盘缓存,内存管理,图片加载优化方面已经做了很好的处理,犯不着自己去实现一套图片加载机制,选择第三方开源库也是理所当然。一般情况,直接用第三方库加载图片即可,几乎不用做额外处理,当然复杂的情况就需要结合第三方库进行优化处理了。

2.按照不同的图片控件尺寸去加载图片,可以减少内存开销,节省资源,提高加载速度。例如微信朋友圈,在列表界面加载缩略小图,点击查看时才加载大图。我们项目开发时,图片上传与存储用的是七牛云存储,而七牛云存储本身提供强大的图片处理API,可以根据请求的链接,获取不同尺寸的图片,方便开发们结合自身项目需求,实现最优图片尺寸加载方案。七牛图片处理API文档地址放在文章最底下,有兴趣的可以了解下。

3.今天的主角LruCache,什么是LruCache?LruCache是android提供的一个缓存工具类,其算法是最近最少使用算法。它把最近使用的对象用“强引用”存储在LinkedHashMap中,并且把最近最少使用的对象在缓存值达到预设定值之前就从内存中移除。其在API12被引进,低版本可以用support包中的类。所以我们用LruCache来缓存加载的Bitmap,当内存低于我们设定的值后,LruCache便会自动帮我们回收用不到的资源。

四、代码

具体原因已经分析,废话不多说,直接上代码

1、LruCacheUtils工具类

import android.graphics.Bitmap;
import android.util.LruCache;/*** Created by leo on 16/8/17.* LruCache 图片缓存优化处理类*/
public class LruCacheUtils extends LruCache<String, Bitmap> {//获取手机内存大小private static int MAXMEMONRY = (int) (Runtime.getRuntime().maxMemory() / 1024);private static LruCacheUtils cacheUtils;private LruCacheUtils(int maxSize) {super(maxSize);}/*** 单例*/public static LruCacheUtils getInstance() {if (cacheUtils == null) {//创建对象时分配缓存,我们取内存的5分之一cacheUtils = new LruCacheUtils(MAXMEMONRY / 5);}return cacheUtils;}@Overrideprotected int sizeOf(String key, Bitmap value) {return value.getRowBytes() * value.getHeight() / 1024;}@Overrideprotected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) {super.entryRemoved(evicted, key, oldValue, newValue);}/*** 清理缓存*/public void clearCache() {if (cacheUtils.size() > 0) {cacheUtils.evictAll();}}/*** 添加缓存图片*/public synchronized void addBitmapToMemoryCache(String key, Bitmap bitmap) {if (cacheUtils.get(key) != null) {return;}if (!isEmpty(key) && bitmap != null) {cacheUtils.put(key, bitmap);}}/*** 获取缓存图片*/public synchronized Bitmap getBitmapFromMemCache(String key) {if (isEmpty(key)) {return null;}Bitmap bm = cacheUtils.get(key);if (bm != null && !bm.isRecycled()) {return bm;}return null;}/*** 移除缓存** @param key*/public synchronized void removeImageCache(String key) {if (isEmpty(key)) {return;}Bitmap bm = cacheUtils.remove(key);if (bm != null && !bm.isRecycled()) {bm.recycle();}}/*** 判断字符串是否为空** @param str* @return*/public boolean isEmpty(String... str) {if (str == null) {return true;}for (String s : str) {if (s == null || s.isEmpty() || s.trim().isEmpty()) {return true;}}return false;}}

2、LruCacheUtils使用

     String url = http://i2.buimg.com/567571/d208d52913b997bb.jpg?imageView2/2/w/200;ImageView photoView = new ImageView();//判断缓存中是否已经缓存过该图片,有则直接拿Bitmap,没有则直接调用Glide加载并缓存BitmapBitmap bitmap = LruCacheUtils.getInstance().getBitmapFromMemCache(url);if (bitmap != null) {photoView.setImageBitmap(bitmap);} else {PhotoLoader.displayImageTarget(photoView, url, getTarget(photoView, url, position));}

3、图片加载方法

    /*** 加载图片 Target** @param imageView* @param target* @param url*/public void displayImageTarget(final ImageView imageView, final String url, BitmapImageViewTarget target) {Glide.get(imageView.getContext()).with(imageView.getContext()).load(url).asBitmap()//强制转换Bitmap.diskCacheStrategy(DiskCacheStrategy.NONE).into(target);}/*** 获取BitmapImageViewTarget*/private BitmapImageViewTarget getTarget(ImageView imageView, final String url, final int position) {return new BitmapImageViewTarget(imageView) {@Overrideprotected void setResource(Bitmap resource) {super.setResource(resource);//缓存Bitmap,以便于在没有用到时,自动回收LruCacheUtils.getInstance().addBitmapToMemoryCache(url, resource);}};}

五、调试查看。

优化完成后,运行程序,在Android studio中找到Monitors一栏,进行图片查看测试,就能清楚的看到内存变化以及释放的过程啦。优化之前是直接使用Glide进行加载图片,内存曾一路飙升到200M,并且很难释放。加了缩略图以及LruCache优化后,内存一直保持在40M-80M之间。测试结果,基本上没有重现过OOM的情况。

PS:建议app中所有加载过的bitmap都直接扔到LruCacheUtils中进行缓存,在bitmap没有使用时,方便系统对齐回收。调用上面代码前,请记得集成Glide开源库哦。如果你使用以上方法进行图片加载优化,还是会出现OOM的话,那就说明......你可能要换手机了……

实例地址:https://github.com/wangzhiyuan888/GlideAndLruCacheDemo

转载于:https://my.oschina.net/u/2933456/blog/785895

图片加载优化,拒绝OOM相关推荐

  1. 前端图片加载优化的各种技巧

    目前的前端图片加载优化技术有很多,像懒加载/预加载,img上的srcset属性以及picture标签,新的图片编码格式以及Client Hints等. Client Hints 顾名思义,client ...

  2. 前端页面图片加载优化

    前端页面图片加载优化 问题:前端页面如果图片资源过多或者过大就会导致用户加载图片时间过长,导致用户体验下降 我总结的优化思路与方法有以下几种 一.将图标换成icon字体管理 如果项目存在大量的图表用的 ...

  3. Android图片加载优化

    一.高效加载大图片 我们在编写Android程序的时候经常要用到许多图片,不同图片总是会有不同的形状.不同的大小,但在大多数情况下,这些图片都会大于我们程序所需要的大小.比如说系统图片库里展示的图片大 ...

  4. Swift - 表格图片加载优化(拖动表格时不加载,停止时只加载当前页图片)

    列表的单元格中包含有图片在开发中很常见.通常我们可以直接在tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIn ...

  5. iOS开发学无止境 - 异步图片加载优化与常用开源库分析

    作者:罗轩(@luoyibu) 网址:http://www.jianshu.com/p/3b2c95e1404f 1. 网络图片显示大体步骤:   下载图片 图片处理(裁剪,边框等) 写入磁盘 从磁盘 ...

  6. html加载时页面闪烁白色背景,解决页面加载闪白问题-背景图片加载优化

    页面加载闪白 今天遇到一个问题,写了一个使用深色背景图的网页,发现访问/刷新时,会出现短暂的闪白现象. 之前使用浅色背景时没有发现过这个问题,搜索半天也没有找到特别直白有效的回答. 找到的几个答案,有 ...

  7. Android图片加载优化方案

    1. 前言 在电商APP中,图片在整个页面中占比最大,清晰高质量的图片能够明显提升转化率.但是APP运行环境错综复杂,往往我们会遇到 图片压缩导致模糊.列表加载长时间显示空白图.查看大图黑屏过久.甚至 ...

  8. 网页图片加载优化方法总结

    目录 1.压缩 2.直接一开始用压缩过的体积小的图,等加载完毕后,再用高清无码图来替换掉 3.使用base64编码代替图片 4.更好的图片格式 5.合并图片sprite(雪碧图) 6.使用css.sv ...

  9. lazyload.css,图片加载优化及图片lazyload自适应 - 轩枫阁

    前言 本文介绍针对轩枫阁V3主题开发过程中,遇到的图片问题及加载优化. 图片居中裁剪 本站的每一篇文章,都会配一张570×200的特色图像,使文章不那么单调. 然而移动端移动端首页图片为60×60的正 ...

最新文章

  1. 中国芯片将靠此超车!RISC-V架构神在哪全解构
  2. PostgreSQL 数据库备份
  3. windows 系统nginx做反向代理实例
  4. .net mysql 备份_windows mysql 自动备份的几种方法
  5. maven 父maven_Maven的春天
  6. 静态类和非静态类的主要差别
  7. 优秀的电商精品素材就到优图
  8. linux ip addr peer,CentOS 7 设置网络IP地址
  9. SQLSERVER使用密码加密备份文件以防止未经授权还原数据库
  10. Actran助力汽车全频率段声学响应预测与优化
  11. Unity进阶之ET网络游戏开发框架 01-下载、运行
  12. oracle 如何实现excel的正态分布函数normdist
  13. 车金融|金融产品规则引擎的前世今生(中篇)
  14. Python ORM框架peewee
  15. 深度学习的开胃菜——常用的机器学习知识梳理
  16. word批注怎么删除计算机名字,【2人回答】Word批注中的名字怎么删除?-3D溜溜网...
  17. 【数据结构/C语言版】【图】邻接表存储
  18. Failed to download https://chrome-infra-packages.appspot.com/dl/flutter/web/canvaskit_bundle 超时 解决办法
  19. 论文:TransVG: End-to-End Visual Grounding with Transformers
  20. HP D380 G9 改IP地址

热门文章

  1. js 常用正则表达式表单验证代码
  2. Springboot配置SSL(https)
  3. 【图】公路车 如何变速 公路车如何调整速度 法嘴怎么打气
  4. C语言中的rand()函数
  5. [NOI2008] 志愿者招募 (费用流)
  6. python热力图代码_python热力图实现简单方法
  7. 线性回归 正则项(惩罚项)原理、正则项的分类与Python代码的实现
  8. rem布局封装及使用
  9. Java基础知识点Day02--数据类型转换与运算符
  10. 新城控股董事长王晓松:逆势增长51%,新城控股挖潜商业板块