美文网首页Android开发Android开发Android进阶之路
drawable和assets加载同一图片是一样大吗

drawable和assets加载同一图片是一样大吗

作者: enjoycc97 | 来源:发表于2019-07-31 16:07 被阅读2次

    面试题:同一张图片在drawable-hdpi和在本地sdcard/assets下加载的大小是一样的吗?

    本文主要是把安卓Bitmap内存占用大小和计算方法学习一下

    实验一:assets下加载测试图片king.png

    把该图片放在assets下,然后调用

    Bitmap  bitmap = BitmapFactory.decodeStream(getAssets().open("king.png"));
    int count = bitmap.getByteCount();
    

    通过日志分析这里计算结果即bitmap.getByteCount()结果是1591448
    而这个与如下计算规则是吻合的,同时打印bitmap.getWidth()和bitmap.getHeight()是同原始图片一致(宽601 高662),打印bitmap.getConfig是ARGB-8888

    计算规则总结:Bitmap内存大小=Bitmap.getWidth*Bitmap.getHeight*4(ARGB-8888质量模式)
    如果是RGB-555则Bitmap大小计算规则=Bitmap.getWidth*Bitmap.getHeight*2
    对于上述结果分析的公式也就是601*662*4=1591448

    小结:对于加载本地文件或者加载assets,如果不设置压缩也就是原图加载,当然这里不知道发现了没有,600*660的图片居然占用1M内存,而我看图片磁盘占用才几十k,感觉优化的算法好厉害。扯远了。
    BitmapFactory.decodeStream默认加载原图不压缩不放大

    实验二:验证drawable下加载图片占用内存大小

    下面做个实验,刚才那个图片放在drawable-hdpi,为了实验准确性,其他drawable都没有这个图片
    同时计算

    Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.king);
    bitmap.getByteCount()
    

    这时候Bitmap占用是多少,
    具体是高883 宽801 占用大小2829132
    那这个值又是怎么算出来的呢,下面一点一点琢磨分析

    先复习一下屏幕适配概念

    屏幕dpi density hdpi这些概念可以找一些资料看一下,这里就直接出概念和定义
    对于dpi : 每英寸多少个像素 公式是勾股定理算出,先计算对角线上像素是c=√aa +bb,而dpi=c/屏幕的英寸;
    屏幕5英寸是说对角线为5英寸;
    density dpi/160 (为什么是除以160呢,这个我也不知道,逃);

    实验参数

    下面以模拟器下加载drawable图片为例子 计算此时Bitmap占用大小
    模拟器参数如下:
    density=2,densitydpi=320,屏幕长1184,宽768

    图片放在drawble-hdpi
    宽601 高662
    空间大小6732字节

    放在assets下原始大小占用内存 1591448==6016624

    而找了一些资料计算规则如下:
    drawable HW Density
    drawable-ldpi 320
    240 120 (0.75)
    drawable-mdpi 480320 160 (1)
    drawable-hdpi 800
    480 240 (1.5)
    drawable-xhdpi 1280*720 320 (2)

    整理结论

    经过自己的观察和整理资料,直接给出结果,drawable下的图片大小是根据drawable目录代表的density和当前手机的
    density关系决定放大或者缩小,和屏幕长宽没有关系,如果drawable目录是hdpi代表1.5,而手机是2则放大图片,
    如果手机是1则缩小图片,放大比例长宽都处理倍数,导致内存占用是倍数的平方

    总结,按照drawable对应的density和当前手机的density
    也可以是densitydpi对应手机densitydpi关系来理解,长宽放大或者缩小此比例
    ,例如本例hdpi(denisity=1.5,densitydpi=240)=》模拟器(denisity=2,densitydpi=320)
    也就是放大4/3倍,约1.333
    ,考虑长宽都放大1.333导致实际占用内存约1.77倍扩大

    二次验证观点

    为了验证本例,我再把图片放到xhdpi,同时删除hdpi下面此图片,占用大小我预期是
    3->2 也就是缩小1.5长宽,得出长441 宽400 占用内存705600
    实际上是长441,宽401,而内存707364。误差2k左右,根据资料查看是
    计算本身有偏差0.5控制,代码如下
    scaledWidth = int(scaledWidth * scale + 0.5f);
    scaledHeight = int(scaledHeight * scale + 0.5f)

    面试题参考答案

    对于加载本地存储图片或者加载assets下图片是通过BitmapFactory.decodeStream按照原图加载,如果选择ARGB-8888图片质量参数则占用内存大小是长4个字节;
    如果加载drawable,BitmapFactory.decodeResource影响因素有2点,1是根据drawable-xhpi,drawable-hdpi等文件夹不同代表原始不同的density ;2是根据当前手机屏幕的density ,通过比较这2个density关系决定放大还是缩小,只有2者相同才会加载原始图片大小

    扯蛋:
    面试不是选择题没有固定答案,如果你以前深挖过这个原理,找过资料分析,自己可以组织语言把这个问题来龙去脉都说清楚而不是一句话就没有了,不然人家问你为什么drawable加载的图片不一样大,又比如怎么压缩图片,比如怎么局部展示图片,比如图片缓存LRU机制,反正这些衍生的东西你最好都知道,不然就会被面试吊打,感觉图片加载其实流程就那些,最好自己掌握主动权然后你来带节奏。网络上不是有个段子,会说话就多说点。另一方面,实际上这道题是考虑不同手机展示的结果是不一样的,如果你匆匆忙忙回答,到时候面试官又会打上考虑问题不周到的标签,估计又要凉凉了,所以还是多问多思考不断自我总结,我们的目标其实也很简单,就是吊打面试官,不对,说错了,是不被面试官吊打哈哈,愿大家面试顺利。

    相关文章

      网友评论

        本文标题:drawable和assets加载同一图片是一样大吗

        本文链接:https://www.haomeiwen.com/subject/mknzrctx.html