最近在做图片相关的需求,总结一下Android图片相关的知识,面试时将这些说
清楚基本就OK啦。感谢开源、Android开发艺术探索、相关优质博文。
一、图片处理背景知识
1.移动端运行可用内存限制(很早之前是单应用16MB)
2.超过限制引发问题:OOM(内存溢出)
3.引发思考:对图片进行压缩处理
二、图片压缩分类
尺寸压缩
概念:
一般是根据控件大小进行比例压缩,被广泛使用的那一套流程,计算合适的采样率再去加载Bitmap到内存涉及知识点:
1.压缩流程解码图片边缘拿到图片像素宽高 options.inJustDecodeBounds = true; 计算压缩采样率 options.inSampleSize = calculateInSampleSize(); 根据采样率压缩尺寸再去解码图片得到Bitmap options.inJustDecodeBounds = false;2.inSampleSize的正确计算姿势
官方Demo里计算采样率可以满足大部分需求,但长宽比差距很大的图片就会有问题,推荐开源框架UIL里的处理方式 区分图片的ScaleType int scale = 1; int widthScale = srcWidth / targetWidth; int heightScale = srcHeight / targetHeight; switch (viewScaleType) { case FIT_INSIDE: if (powerOf2Scale) { while (srcWidth / 2 >= targetWidth || srcHeight / 2 >= targetHeight) { // || srcWidth /= 2; srcHeight /= 2; scale *= 2; } } else { scale = Math.max(widthScale, heightScale); // max } break; case CROP: if (powerOf2Scale) { while (srcWidth / 2 >= targetWidth && srcHeight / 2 >= targetHeight) { // && srcWidth /= 2; srcHeight /= 2; scale *= 2; } } else { scale = Math.min(widthScale, heightScale); // min } break; } if (scale < 1) { scale = 1; }3.拓展话题:ScaleType
matrix(默认) center centerCrop centerInside fitCenter fitEnd fitStart fitXY4.误区盲点
这种方式不一定会将图片字节大小降下去,有时把一张图片缩小一点点,图片本身所占内存反而增多了质量压缩
概念:
对图片的品质进行压缩,可以明显减少图片所占字节大小,例如微信分享限制缩略图大小不超过32KB压缩方法:
1.读取Bitmap字节大小
ByteArrayOutputStream baos = new ByteArrayOutputSream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);//这里100的话表示不压缩质量 long length=baos.toByteArray().length;2.降低品质进行压缩
上面compress方法第二个参数的取值[1,100]
一般80往下就压不动了,压缩算法不是按区间等分
[80,100]之间较为明显涉及知识点:
1.第一个参数区别Bitmap.CompressFormat.PNG Bitmap.CompressFormat.JPEG2.第二个参数区间及含义
三、图片色彩样式
ALPHA_8
每个像素只占1个字节,只能代表透明度,没有颜色属性ARGB_4444
每个像素要2字节,带透明度的颜色,官方不推荐使用了ARGB_8888
每个像素要4字节,带透明度的颜色RGB_565
每个像素要2字节,不带透明度的颜色涉及知识点:
1.ARGB含义
2.数字含义拓展:
1.图片放在不同drawable-*dpi下的区别
2.为什么要美术切多套图或一套图?
3.mipmap-*dpi和drawalbe-*dpi区别
四、图片缓存
java中四种引用类型
1.强引用
2.软引用SoftReference
3.弱引用WeakReference
4.虚引用古老的方式
二级缓存机制
设置两个缓存池,一个强引用,一个软引用
强引用作为一级缓存LinkedHashMap重写removeEldestEntry方法,删除最不常用对象 Android 3.0后的升级
1.实践中软引用没啥卵用
官方文档在实践中,软引用在缓存的处理上是没有效率的。运行时没有足够的信息用于 判断哪些引用要清理回收还有哪些要保存。最致命的,当同时面对清理软引用 和增加堆内存两种选择时它不知道做什么。对于你应用的每一个引用都缺乏有 价值的信息,这一点限制了软引用让它的可用性十分有限。过早清理回收的引 用导致了无必要的工作,而那些过晚清理掉的引用又浪费了内存。2.引入LruCache
近期最少使用算法,原理同LinkedHashMap逻辑,使用上要重写
sizeOf()方法
指定缓存计算大小的单位是字节,创建LruCache时传入总值一般为Runtime可用
内存的1/8.常说的三级缓存
1.流程
加载一张图片,先从内存缓存中找,没有从磁盘缓存中找,再没有从网络下载 下载完后在两个缓存区分别保存一份,如果磁盘中有,就直接在内存缓存中保 存一份2.使用
内存缓存 -> LruCache 磁盘缓存 -> DiskLruCache3.网络异步下载,Handler切换线程,在UI线程设置
4.优势:
1.为用户节省流量 2.响应速度快,内存>磁盘>下载自己打造ImageLoader
1.图片的同步加载
2.图片的异步加载
3.图片的压缩处理
4.内存缓存
5.磁盘缓存
6.网络下载图片(HttpUrlConnection 或网络框架 解耦和可配置)拓展
在列表风格的控件加载图片时,通过监听滑动事件,当状态为Fling的时候停止加载
在停下来的时候再去加载(照片墙 缓存策略使用 LIFO )
开启硬件加速android:hardwareAccelerated="true"
五、开源框架
使用原则
不要使用大而全的库,要选择专一功能的不要使用已经停止维护的调研包体大小和方法数,尽量轻量级二次封装,便于库的切换与调用截至2016.10.22开源库对比
UniversalImageLoader
老牌著名库,作者停止维护了,别用了xUtils3
典型的大而全的库,依赖注入,DB,网络,图片,别用了Volley
网络框架,同时也有和UIL类似的ImageLoader,包体和方法有限制可以采用
但不支持加载本地图片,要自己修改,功能不强大Picasso
JakeWharton大神的库,体积较小,无本地缓存,可结合Square全家桶OkHttpGlide
Google推荐的图片库,支持GIF、WebP、Video多种媒体格式,网络配置可修改
(默认UrlConnection 可结合Volley/OkHttp )色彩格式默认RGB565Fresco
FaceBook搞的大东西,屌炸天但体积庞大,分分钟65K
可参见廖祜秋大神的Fresco中文站点学习总结
作为一名Google粉,目前项目以开发SDK为主,别想了,拥抱Glide…