一、Glide介绍:Glide做了哪些优化?
implementation 'com.github.bumptech.glide:glide:4.1.1'- 初音绿:#39c5bb
- 使用深拷贝+预加载解决切换图片闪烁问题
- 正常情况占位图被替换确实是正常的,目标加载后占位图消失【过度绘制看过】;
- 部分情况有白边其实是Glide的占位图背景【有些option不兼容】,缺点 有些时候刷新会闪烁,用background取代placeholder可以解决这个问题;Glide显示图片闪烁问题;
- 问题样例:Glide4.0 centerCrop属性和圆角 冲突_glide centercrop与圆角冲突,有效果,但存疑,个人不太喜欢用这个;
- 评论区解决方案:
val options = RequestOptions().transform(MultiTransformation(CenterCrop(),RoundedCorners(dp2px(2f)))),但实测 高斯模糊和圆角一起设置的话样式不对的,建议圆角用ImageViewFilter;
2、 缓存相关资料:Gllide缓存配置
- 磁盘缓存效果非常好用。
- 禁用内存缓存和磁盘缓存对 运行时内存影响不大。
- 查阅资料:使用使用内存缓存的目的是为了防止重复加载这个逻辑。
3、关于ssl验证:Glide基本使用以及加载https图片(配合OkHttp实现)
二、CardView特征,圆角绘制的优点
- 在布局层划分出圆角内为可绘制区域
特征:卡片+阴影效果,切圆角也方便,虽然view多了一层,但透明色并不会导致多绘制一层。
内存实验与对照(8张图片,vp 先滑到最右再最左,保存预加载1;三组view对照,每组四次(前两次为首次加载,后两次为读缓存)):结论:内存占用差不多,个人喜欢用CardView+Image。
| 方案 | 前两次 | 第三次 | 第四次 | 优劣 |
|---|---|---|---|---|
| CardView | 208~211 | 202 | 202 | 好处是限定了父布局限定尺寸,就不会有背景边角露出来的问题 |
| Glide切圆角 | 208~208 | 203 | 203 | 好处是少包一层,圆弧是绘制出来的 |
| 自定义view+Glide不切圆 | 207~208 | 206 | 205 | 3.2中的自定义view感觉不如cardview,虽然兼顾两个的优势,但同样增加了开销,上手成本也高。 |
1、CardView参数: Android CardView简单使用
1、app:cardCornerRadius:绘制圆角,cardBackgroundColor 设置透明(其取代bg,且只能设置color,透明不会增加一层过度绘制)。
2、 Glide法:
1、 基本写法:Android标准Glide加载圆形图和圆角矩形图_glide 矩形
- 发现image不设置ScaleType挺正常的,设置圆角会变形。
2、解决变形:Glide 图片圆角失效问题_glide 圆角无效
- 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的关系、区别
- 例如代码中通过getDrawable获取图片;
- BitmapDrawable将两个联系起来,安卓通过View展示一张具体的图片时会把Bitmap转化为BitmapDrawable,然后View通过Canvas来渲染BitmapDrawable到画布上。
2、为什么要用bitmap:谈谈安卓的Bitmap与Drawable_bitmap和bitmapdrawable
- 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代替
- 目的:为了资源得到正常释放
- 样例链接
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:在图片切换时的占位图,新图片加载成功后,占位图的占位会被其取代;
- placeholder配合crossFade()效果不错;
五、监听
一、【取色】提取图片颜色Palette
1、AndroidX 使用Glide和Palette获取图片的主色调
- 方法封装
- generate回调是异步的,且不能在监听return ,因为会return@generate,所以直接设置view而不是return色值;
2、Android Material Design 系列之 Palette 开发详解
4、获取适合的文字颜色:Android Jetpack:利用Palette进行图片取色
六、高斯模糊
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、杂项自测:
- 正常情况下,Glide会自动释放内存:一个Activity加载10张Activity,返回后会立马释放掉,就算有adapter与holder记录也会释放掉。

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

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

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

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

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

- 下列两个方法对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 //获取柔和的亮
异常:
关于加载一张超大分辨率的研究
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)
}