【Android笔记】Glide,CardView,图片管理,色彩模式

796 阅读8分钟

一、Glide介绍:Glide做了哪些优化?

  • implementation 'com.github.bumptech.glide:glide:4.1.1'
  • 初音绿:#39c5bb
  • 使用深拷贝+预加载解决切换图片闪烁问题

1、基本使用及显示 Gif 和 Video

  • 正常情况占位图被替换确实是正常的,目标加载后占位图消失【过度绘制看过】;
  • 部分情况有白边其实是Glide的占位图背景【有些option不兼容】,缺点 有些时候刷新会闪烁,用background取代placeholder可以解决这个问题;Glide显示图片闪烁问题
  • 问题样例:Glide4.0 centerCrop属性和圆角 冲突_glide centercrop与圆角冲突,有效果,但存疑,个人不太喜欢用这个;
  • 评论区解决方案:val options = RequestOptions().transform(MultiTransformation(CenterCrop(),RoundedCorners(dp2px(2f)))),但实测 高斯模糊和圆角一起设置的话样式不对的,建议圆角用ImageViewFilter;

2、 缓存相关资料:Gllide缓存配置

  1. 磁盘缓存效果非常好用。
  2. 禁用内存缓存和磁盘缓存对 运行时内存影响不大。
  • 查阅资料:使用使用内存缓存的目的是为了防止重复加载这个逻辑。

3、关于ssl验证:Glide基本使用以及加载https图片(配合OkHttp实现)

二、CardView特征,圆角绘制的优点

  • 在布局层划分出圆角内为可绘制区域

特征:卡片+阴影效果,切圆角也方便,虽然view多了一层,但透明色并不会导致多绘制一层。

内存实验与对照(8张图片,vp 先滑到最右再最左,保存预加载1;三组view对照,每组四次(前两次为首次加载,后两次为读缓存)):结论:内存占用差不多,个人喜欢用CardView+Image。

方案前两次第三次第四次优劣
CardView208~211202202好处是限定了父布局限定尺寸,就不会有背景边角露出来的问题
Glide切圆角208~208203203好处是少包一层,圆弧是绘制出来的
自定义view+Glide不切圆207~2082062053.2中的自定义view感觉不如cardview,虽然兼顾两个的优势,但同样增加了开销,上手成本也高。

1、CardView参数: Android CardView简单使用

1、app:cardCornerRadius:绘制圆角,cardBackgroundColor 设置透明(其取代bg,且只能设置color,透明不会增加一层过度绘制)。

2、 Glide法:

1、 基本写法:Android标准Glide加载圆形图和圆角矩形图_glide 矩形

  1. 发现image不设置ScaleType挺正常的,设置圆角会变形。

2、解决变形:Glide 图片圆角失效问题_glide 圆角无效

  1. RequestOptions多传个ScaleType。

3、 自定义View法:

1、 Android圆角布局,你有几种实现方式? 这种写法也很简单,但外面包了一层,感觉不如CardView。

2、 继承ImageView法:较为复杂,且涉及背景圆角与三种绘制方式:一次搞懂怎么设置圆角图片,ImageView的各种圆角设置 - 掘金 (juejin.cn)

4、补充 官方方案 ImageFilterView,未对比性能

ConstraintLayout官方提供圆角ImageFilterView

  • 实际上也是对src进行操作,背景仍然是方形的,只有CardView是划出圆角内绘制区;

三、图片管理

1、drawable与mipmap文件夹: Android中drawable和mipmap到底有什么区别

1、一般mipmap放icon资源,drawable放图片资源;drawable中会保留当前对应资源文件夹,但只对aab有效,其实对apk来说都会保留,没啥差别。

2、Bitmap和Drawable的关系、区别

1、 Bitmap和Drawable的区别

  1. 例如代码中通过getDrawable获取图片;
  2. BitmapDrawable将两个联系起来,安卓通过View展示一张具体的图片时会把Bitmap转化为BitmapDrawable,然后View通过Canvas来渲染BitmapDrawable到画布上。

2、为什么要用bitmap:谈谈安卓的Bitmap与Drawable_bitmap和bitmapdrawable

  1. Bitmap存储的是像素点,代表具体的一张图片信息。安卓中对图片的裁剪、缩放等一系列的操作需要把图片文件以Bitmap的形式加载到内存中进行操作。

3、 Bitmap相关方法:Android Bitmap最全面详解

4、Android Bitmap详细总结之Bitmap.Config色彩模式

  • ALPHA_8,RGB_565,ARGB_4444,ARGB_8888(安卓默认),
  • 1,2,2,4;像素总数*字节数=图片内存占用。

5、 不透明度:Android颜色透明度(不透明度)计算

  • 口诀:100%的不透明就是0%的透明;
  • alpha为0的话不影响点击状态。

四、监听

参考:Glide使用详解

  • Glide可以加载超大分辨率图但会主动压缩

1、Target

1、SimpleTarget(自由使用Target)和ViewTarget(自定义View中使用Target)废弃了,分别由CustomTarget和CustomViewTarget代替

  1. 目的:为了资源得到正常释放
  2. 样例链接
  Glide.with(this@MainActivity)
       .load(imgArray[position % imgArray.size])
       .into(object : CustomTarget<Drawable>() {
              override fun onResourceReady(
              resource: Drawable,
              transition: Transition<in Drawable>?
              ) {
                 TODO("Not yet implemented")
                }

              override fun onLoadCleared(placeholder: Drawable?) {
                 TODO("Not yet implemented")
                }
             })

2、Placeholder

1、placeholder:在图片切换时的占位图,新图片加载成功后,占位图的占位会被其取代;

2、Glide - 占位符 和 渐现动画

  • placeholder配合crossFade()效果不错;

五、监听

一、【取色】提取图片颜色Palette

1、AndroidX 使用Glide和Palette获取图片的主色调

  • 方法封装
  • generate回调是异步的,且不能在监听return ,因为会return@generate,所以直接设置view而不是return色值;

2、Android Material Design 系列之 Palette 开发详解

3、 【Android+Kotlin】自适应CoordinatorLayout,AppBarLayout,CollapsingToolbarLayout,Palette与FloatingActionButt_android appbarlayout 联动滑动

4、获取适合的文字颜色:Android Jetpack:利用Palette进行图片取色

六、高斯模糊

1、android 高斯模糊几种方案比较与实现

2、Android高斯模糊(毛玻璃效果)蒙层库-ShapeBlurView

  • 这个也蛮有意思的,固定一个位置高斯模糊
  • 在Dialog中用这个,如果Activity有UI变化,这个会有异常;

附:缓存相关资料自测:Android Studio 3.0 利用 Android Profiler 测量应用性能

1、RecycleView条目被回收时手动回收该部分内存,有点意思

1、android glide内存溢出,Recyclerview使用Glide加载大量图片时出现内存溢出(OOM)

2、Glide 这样用,更省内存!!

1、How to optimize memory consumption when using Glide

3、杂项自测:

  1. 正常情况下,Glide会自动释放内存:一个Activity加载10张Activity,返回后会立马释放掉,就算有adapter与holder记录也会释放掉。

image.png

  1. 磁盘缓存的好处:走默认设置,退出销毁,断网再进是能显示的,去掉磁盘和内存缓存后(13,43)下次进改页面图片会重新拉,断网再就不显示了。(不加是12-22),用持有 SparseArray也是不影响的。

image.png

  1. 页面不动,调用clear方法,内存会增加

image.png

  1. 如何在使用滑行|时优化内存消耗作者:宝琳娜·萨多夫斯卡 |ProAndroidDev

  2. 关于第一点只加载少量图,结论正确;但使用adapter大图加载多张就会这样,且退出后一直保持那个水平线,手动gc也不行。 image.png

  3. 纯Activity+ScrollView滑动也会有这种问题

image.png

  1. clear方法的作用:只是把native的占用去掉

image.png

  1. 下列两个方法对Memory影响不大
  • .skipMemoryCache( true )

  • .diskCacheStrategy( DiskCacheStrategy.NONE )

OpenCV

一、基本信息

1、参考链接:Android-拍照后使用OpenCV进行图像模糊度检测_android开发判断图片是否清晰

2、关于配置:OpenCV android sdk配置OpenCV android NDK开发实例 - 掘金 (juejin.cn)

3、清晰度识别:Android OpenCV (一) 基础API 清晰度亮度识别 - 掘金 (juejin.cn)

其他

object PaletteHelper {

    /**
     * 设置图片主色调
     */
    @JvmStatic
    fun setPaletteView(imageView: ImageView, bitmap: Bitmap?, @ColorRes defaultColor: Int) {
        if (bitmap == null) {
            imageView.setBackgroundColor(imageView.resources.getColor(defaultColor))
        } else {
            Palette.from(bitmap).maximumColorCount(10).generate { palette ->
                val s: Palette.Swatch? = palette?.dominantSwatch //主色调
                if (s != null) {
                    imageView.setBackgroundColor(s.rgb)
                } else {
                    imageView.setBackgroundColor(imageView.resources.getColor(defaultColor))
                }
            }
        }
    }

    /**
     * 设置图片主色调
     */
    @JvmStatic
    fun setPaletteViewGuadual(imageView: ImageView, bitmap: Bitmap?, @ColorRes defaultColor: Int) {
        if (bitmap == null) {
            imageView.setBackgroundColor(imageView.resources.getColor(defaultColor))
        } else {
            Palette.from(bitmap).maximumColorCount(10).generate { palette ->
                val s: Palette.Swatch? = palette?.dominantSwatch //主色调
                if (s != null) {
                    val colors =
                        intArrayOf(s.rgb, imageView.resources.getColor(R.color.transparent))
                    val drawable = GradientDrawable(GradientDrawable.Orientation.BOTTOM_TOP, colors)
                    drawable.gradientType = GradientDrawable.LINEAR_GRADIENT;
                    imageView.background = drawable
                } else {
                    val colors =
                        intArrayOf(defaultColor, imageView.resources.getColor(R.color.transparent))
                    val drawable = GradientDrawable(GradientDrawable.Orientation.BOTTOM_TOP, colors)
                    drawable.gradientType = GradientDrawable.LINEAR_GRADIENT;
                    imageView.background = drawable
                }
            }
        }
    }
}

//                    val s1: Palette.Swatch? = palette.vibrantSwatch //获取到充满活力的这种色调
//                    val s2: Palette.Swatch? = palette.darkVibrantSwatch //获取充满活力的黑
//                    val s3: Palette.Swatch? = palette.lightVibrantSwatch //获取充满活力的亮
//                    val s4: Palette.Swatch? = palette.mutedSwatch //获取柔和的色调
//                    val s5: Palette.Swatch? = palette.darkMutedSwatch //获取柔和的黑
//                    val s6: Palette.Swatch? = palette.lightMutedSwatch //获取柔和的亮

异常:

Android java.lang.IllegalArgumentException: You cannot start a load for a destroyed activity解决方案 - mingruqi

关于加载一张超大分辨率的研究

1、现象:使用Glide加载一张1080x12768的图会非常糊,NestedScrollView嵌套ImageView

  • 宽度分辨率相同的情况下,高度越高越糊
  • 如果把NestedScrollView去掉的话,因为高度定死,高度占比约高的宽度越下,可能在这个和Glide的机制有关

2、解决方案

1、使用setImageResource【speed:372 图片清晰】

2、loadUrlOrigin【speed:138 图片略糊,还是推荐这个,性能好】

fun ImageView.loadUrlOrigin(uri: Int) {
    Glide.with(this)
        .load(uri)
        .apply(
            RequestOptions()
                .override(com.bumptech.glide.request.target.Target.SIZE_ORIGINAL)
                .downsample(DownsampleStrategy.NONE)
        )
        .into(this)
}

image.png

image.png

image.png

image.png