Android ImageView 详解

目录

一、图片加载方法

二、图片缩放类型

三、updateDrawable() 原理

四、图片加载时会按缩放类型,会影响图片占用的内存大小吗?

五、总结


一、图片加载方法

在项目中,加载图片时,都会用到 ImageView,对应的几种设置图片的方式有如下几种:

  • 在布局文件中设置属性 android:src=“@drawable/resId” 加载本地图片
  • setImageResource(int resId); 加载drawable文件夹中的资源文件
  • setImageURI(Uri); 加载手机内存卡中的图片格式文件
  • setImageBitmap(Bitmap); 加载 Bitmap
  • setImageDrawable(Drawable); 加载 Drawable

通过上述流程图,可以得知:

  • 所有的图片格式,不管是资源,还是 Uri 还是 Bitmap ,都会转化为 Drawable;
  • setImageURI(Uri) 方法,涉及到将文件转化为文件流,然后将文件流解析为 Bitmap 操作,需要注意的是在主线程中做这些操作,可能会造成延时;
  • 针对性能方面,给上述加载图片方法排序,从劣到优,可以这样来:setImageURI() < setImageBitmap() < setImageRecource() < 属性设置 < setImageDrawable() ,能肯定的是,setImageDrawable() 是最优设置方法。

    主要方法:updateDrawable(Drawable)

    主要是根据 ImageView 设置的图片缩放类型确定其内容(即图片)绘制的边界,所以在这之前,需要知道关于 scaleType 缩放类型的一些事。

 

二、图片缩放类型

ImageView 对应的图片缩放类型,属性名为 scaleType,系统给出了八种缩放类型,对应含义和作用如下图所示: 

 网上大多以很形象的图展示各种缩放类型下ImageVIew加载图片的场景,这样看起来更容易理解,链接: ImageView的ScaleType原理及效果分析

三、updateDrawable() 原理

对缩放类型有了清晰的认识后,再来看 updateDrawable() 方法具体做了哪些操作,源码流程如下:

四、图片加载时会按缩放类型,会影响图片占用的内存大小吗?

这里就有一个疑问了,既然图片加载时会按缩放类型放大或缩小图片,那么这会影响图片占用的内存大小吗?

测试场景:让 ImageView 加载同一张图片,然后以不同的 scaleType 进行加载,查看该图片占用的内存是否会改变?设置 vWidth = 200dp, vHeight = 160dp,加载图片原始大小:144x144 ,设备屏幕尺寸:1080x1920。
测试代码:

 Log.e("ImageView", "scaleType = " + iv_img.getScaleType().toString());  // 默认为 FIT_CENTER

        final Drawable drawable = iv_img.getDrawable();
        int iWidth = drawable.getIntrinsicWidth();   // 216
        int iHeigth = drawable.getIntrinsicHeight(); // 216

        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_logo);
        Log.e("ImageView", "bmap size = " + (bitmap.getWidth() + ", " + bitmap.getHeight()) + ", " + bitmap.getAllocationByteCount());

        // 216 216 432
        Log.e("ImageView", "drawable size = " + (iWidth + ", " + iHeigth));

        iv_img.post(new Runnable() {
            @Override
            public void run() {
                Rect bounds = drawable.getBounds();
                int boundsW = bounds.right - bounds.left;
                int boundsH = bounds.bottom - bounds.top;
                // 216 216
                Log.e("ImageView", "bounds size = " + (boundsW + ", " + boundsH));
            }
        });

测试结果:

  • 默认缩放类型FIT_CENTER:bmpW_H = drawableW_H = 216x216, bounds = 216x216,分配内存大小 = 186624
  • 设置缩放类型FIT_XY:bmpW_H = drawableW_H = 216x216, bounds = 600x480,分配内存大小 = 186624

只设置两组区别比较到的缩放内存,从得到的结果可知缩放类型不会影响图片占用内存大小,只会影响 Drawable 在绘制图片到屏幕时的区域大小,可以看一下 Drawable ,其实也具备绘制功能。其实了解如何计算图片占用内存,就比较清楚,将图片转化为 Bitmap ,然后分场景计算:

  • 加载资源文件时,计算的图片占用内存大小同图片所在drawable 文件夹和展示图片设备的分辨率有关;
  • 加载内部存储中的图片文件时,则同设备屏幕密度无关,为图片本身大小。

可以明确的是,图片最终是以 Bitmap 形式存在于内存中的,ImageView 的缩放类型只是将图片展示的区域按缩放规则进行划定,并没有对图片本身产生作用,所以 scaleType 缩放对图片占用的内存大小并没有什么关系。

五、总结

了解本质之后,对图片的加载也有了大半的认识,在此做一下对 ImageView 的使用和认知做一些总结:

  • setImageURI() 方法存在对 Uri 代表的图片文件转化为文件流而后解析为Bitmap 的操作,可能会存在延时,需要注意一下;
  • 设置图片的最优方式是 setImageDrawable() 方法;
  • 在布局中通过 src 属性展示图片 实际调用的并非 setImageResource() 方法,而是先将 resId 转化为 Drawable,然后通过 setImageDrawable() 方法加载;
  • Drawable 是Android 系统中图片绘制前的最终形式,图片如何绘制到 canvas 上,也是通过 Drawable 来的;区别于在内存中存在的最终形式为 Bitmap;
  • 自定义 View 时,绘制图片,使用 Drawable.setBounds() 确定边界后,再调用 drawable.draw(canvas) 方法绘制 会比 canvas.drawBitmap() 更简单强大,前者还能绘制 shape xml 文件转化的图片;
  • ImageView 默认缩放类型为 FIX_CENTER;
  • ImageView 缩放内存对加载图片本身占用的内存大小并没有关系,仅仅是缩放图片内容展示的边界而已;
  • 图片占用内存大小,若为资源文件,则同drawable文件夹代表的密度和设备屏幕密度有关;若为网络或文件,则为图片本身大小;
  • 图片的压缩方式分两种:质量压缩和分辨率压缩,前者能减少图片质量,但对图片分辨率并没有影响,图片占用的内存大小没有改变,常运用于 上传网络图片时上传字节大小有限制;后者压缩分辨率,会改变图片的清晰度,占用内存也会减少。

 


 

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黄毛火烧雪下

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值