加载本地图片模糊,Glide加载网络图片却很清晰

问题

前几天做项目,同事遇到个问题,加载drawable中图片很模糊,用Glide加载就清晰,其中图片放在xhdpi文件夹中,屏幕分辨率是1280x720,奇怪的是xhdpi的图片对应的就是1280x720的分辨率,为什么会不清晰呢?我后来写了个demo验证了下,发现确实会不清晰,如下:

加载本地drawable不清晰

最后一个glide加载清晰
首先是想起以前看过的文章 Android 开发绕不过的坑:你的 Bitmap 究竟占多大内存?Android应用性能优化系列视图篇——隐藏在资源图片中的内存杀手看完这两篇文章应该就能理解为什么图片会模糊,简单说就是像放在drawable-mdpi、hdpi、xhdpi、xxhdpi中的图片分别是对应不同分辨率屏幕的,假如我只在xxhdpi放一张图片,在较低分辨率的屏幕上会压缩,如果在mdpi中放一张图片,在高分辨率屏幕上就会放大,计算公式如下:

资源图片最终大小 = 宽 x(设备密度 / 资源维度密度)x 高(设备密度 / 资源维度密度) x 4

设备密度是说不同分辨率的屏幕对应的密度,资源维度密度是说drawable-mdpi、hdpi、xhdpi、xxhdpi这些分别也对应不同的密度,具体见下表

文件夹资源维度密度对应分辨率设备密度
drawable-mdpi160320x480160
drawable-hdpi240480x800240
drawable-xhdpi320720x1280320
drawable-xxhdpi4801080x1920480
drawable-xxxdpi6401440*2560560

其中资源维度密度是系统规定好的,因为屏幕分辨率和屏幕尺寸不同,设备密度这个值可以用 getResources().getDisplayMetrics().densityDpi查看,我测试的电视打印出来的设备密度是240,很奇怪的不是320,后来在这篇文章android 手机屏幕密度等级和屏幕逻辑尺寸才知道这个值是厂商定义的,所以同分辨率不同屏幕尺寸的设备密度会有不同,开始时并不知道这一点,只是认为放在xhdpi文件夹中就应该是对应的1280x720分辨率的屏幕,就不应该会被压缩。

解答

回到我们刚才的问题,图片尺寸是411x195,使用本地图片和glide加载内存占用分别是179871和320580

根据公式: 资源图片最终大小 = 宽 x(设备密度 / 资源维度密度)x 高(设备密度 / 资源维度密度) x 4

用glide加载可以不被压缩,所以内存占用=411x195x4=320580,和打印值相等。计算本地加载时宽=411x240/320=308.25取整308,高195x240/320=146.25取整146,308x146x4=179872,和打印出来的相等。到这问题也算是解决了,开始是因为不知道屏幕密度是由厂商规定的,并不是由屏幕分辨率规定的,所以就算把图片放到的分辨率对应的drawable中还是有可能会被压缩。

总结

我们Android里面的长度单位推荐用dp,表示和设备无关的一个单位,用来在不同分辨率上看起来效果一样,或者说在相同分辨率不同屏幕尺寸下看起来效果不一致。dp以160为1,表示在160密度的屏幕上1dp表示1px,那么在320的屏幕上1dp表示2px,在640的屏幕上1dp表示4px,以此类推。 假定有两块5寸屏幕,一块1280x720分辨率,一块1920x1080,现在上面放一个80dpx80dp的图片,这个图片在1280的屏幕上最终显示160pxx160px,在1920上显示240pxx240px, 这样160/720=0.222,240/1080=0.222,这样图片在屏幕所占比例一样,即在低分辨率上能放几个按钮,在高分辨率上也是放几个按钮,位置大小看起来都一样。

但是一般的同分辨率下电视屏幕都要比手机屏幕大,手机一排放两个按钮可能就差不多了,但是电视上如果只放两个按钮就会显得按钮很大,很不协调,电视可能能放下四个甚至更多按钮,这相当于是屏幕越大应该显示的东西越多。所以这才有了厂商自定义的设备密度,比如同样1920x1080分辨率,手机的设备密度是480,电视的设备密度可能只有240(我测试的一款电视只有213),根据公式:

资源图片最终大小 = 宽 x(设备密度 / 资源维度密度)x 高(设备密度 / 资源维度密度) x 4 100dpx20dp的按钮在手机上实际300pxX60px,但在电视上只有150pxX30px,在1080手机上一排最多只能放3个了,但在电视上就可以1080/150=7个(先不考虑电视的横竖屏), 当然实际不可能会放7个这么多。手机上一个宽度占屏幕宽度三分之一的按钮看起来效果是比较好的,但是如果占了电视屏幕宽度三分之一看起来就不那么优雅了。

思考

上面讨论的是手机和电视这样相比屏幕尺寸差别很大的,但是只针对电视,不同厂商不同尺寸电视(40寸,55寸,65寸这样的尺寸),设备密度差别也很大,比如我测试的两个电视都是1280x720的,但是一个密度是213,一个是240,但是具体屏幕尺寸都是一样的21寸,如果我们继续使用dp,sp这样的单位根据上面的公式可知:实际宽=宽x设备密度/资源维度密度,导致宽高在设备密度为213的上面的会比240上面的小,所以最终采用的是px单位,以1280x720为标准,在不同分辨率屏幕上计算实际的像素值,比如以1280x720为模板设计的图片尺寸是100x100,那么在1920x1080上面就是150x150大小,这样就能比较完美适应不同屏幕了

Glide 是一个高效、开源、 Android设备上的媒体管理框架,它遵循BSD、MIT以及Apache 2.0协议发布。Glide具有加载本地图片、远程图片、GIF动画等功能。项目地址:https://github.com/bumptech/glide 你也可以直接下载jar包:https://github.com/bumptech/glide/releases 如何使用:创建个ImageView2. 获取图片并填充到ImageView  获取远程图片: Glide.with(this).load("http://www.see-source.com/source/img/logo_01.png").into(iv);   获取本地图片Glide.with(this).load(R.drawable.logo_01).into(iv);  获取GIF动画图片Glide.with(this).load(R.drawable.image02).into(iv);image02.gif是个动画图片具体功能如下:GIF 动画的解码 :通过调用Glide.with(context).load(“图片路径“)方法,GIF动画图片可以自动显示为动画效果。如果想有更多的控制,还可以使用Glide.with(context).load(“图片路径“).asBitmap()方法加载静态图片,使用Glide.with(context).load(“图片路径“).asGif()方法加载动画图片本地视频剧照的解码: 通过调用Glide.with(context).load(“图片路径“)方法,Glide能够支持Android设备中的所有视频剧照的加载和展示缩略图的支持: 为了减少在同一个view组件里同时加载多张图片的时间,可以调用Glide.with(context).load(“图片路径“).thumbnail(“缩略比例“).into(“view组件“)方法加载一个缩略图,还可以控制thumbnail()中的参数的大小,以控制显示不同比例大小的缩略图Activity 生命周期的集成: 当Activity暂停和重启时,Glide能够做到智能的暂停和重新开始请求,并且当Android设备的连接状态变化时,所有失败的请求能够自动重新请求转码的支持: Glide的toBytes() 和transcode() 两个方法可以用来获取、解码和变换背景图片,并且transcode() 方法还能够改变图片的样式动画的支持: 新增支持图片的淡入淡出动画效果(调用crossFade()方法)和查看动画的属性的功能OkHttp 和Volley 的支持: 默认选择HttpUrlConnection作为网络协议栈,还可以选择OkHttp和Volley作为网络协议栈其他功能: 如在图片加载过程中,使用Drawables对象作为占位符、图片请求的优化、图片的宽度和高度可重新设定、缩略图和原图的缓存等功能
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值