Android如何优雅地解决重复Drawable资源

简介: Android如何优雅地解决重复Drawable资源

1. 前言


最近鸿洋大神和路遥大佬分别在他们的公众号上发布了关于解决Shape/Selector冗余的方案。这篇文章在上周末就已经写好了。虽然类似的解决方案特别多,实现思路也都差不多。但我仍然要安利一下我的这个解决方案。原因有以下几点。

  1. 很纯粹,就是用代码的方式实现了xml实现的Drawable,不用重写自定义View或者Hook系统的基础组件。
  2. 最大程度的复刻xml所拥有的能力,甚至连单位dp还是px的api都提供好了。
  3. 使用Builder模式将方法和参数都约束起来,使用起来很方便,不用去众多的api中寻找方法。结合Kotlin的语法,一个字“香”。
  4. 内部实现了缓存策略,以及根据Hash判重策略,这也是目前市面上的其他解决方案所没有的。

当然美中不足的是,目前所有的xml替换都是需要手工去完成,如果在编译期能够通过gradle插件自动转换,那就完美了。如果您有相关的经验,可以尝试一起把这个库做得更好。


2. Android为什么用xml生成Drawable



xml是Android系统中生成Drawable的首选方案,所以很多同学都习惯了使用xml生成GradientDrawable和SelectorDrawable,它们确实很方便。但是随之而来的问题,我相信很多同学都是深有体会的,哪怕是GradientDrawable中一个圆角大小的改动,或者一个颜色值的改动,都需要在原来的xml文件基础上拷贝一份新的xml文件,这样导致项目中的drawable文件越来越多。甚至一些编码规范没做好的团队,明明完全一样效果的drawable在项目中也有可能出现多份。


针对这种情况,有没有必要处理呢?大部分的xml文件也就1 2kb,占用空间很小,对包体积大小影响也没那么大。虽然说Android系统Drawable缓存是以文件名为维度的,但是它的回收策略做的挺棒的,冗余的xml对内存占用有影响,但没那么大。


那就任由文件数量膨胀吗?我觉得答案是见仁见智的,不处理也可以,无非就是写起来臃肿点呗,至少不用花时间去想一套解决方案。当然我们也可以精益求精,使用代码生成Drawable方案,实现与xml完全一样的效果,同时又能避免冗余的xml文件出现。

意外的收获👉 在项目使用svg作为图片时,发现在Android5.0 和Android6.0手机上,xml定义的selector图片显示不正常。究其原因是因为Android7.0以下不支持svg格式的fillType,导致selector渲染出来的图片有问题。想了很多方法都无法解决,最终通过代码生成selector的方案解决了。


在开始写通过代码生成Drawable之前,首先思考一个问题?为什么Android系统会首选xml生成Drawable方案呢?

通过分析xml渲染Drawable原理,我觉得系统兼容可能是使用xml的一个重要原因。以GradientDrawable的setPadding方法为例,该方法在Android Q版本引入。如果我们在xml文件引入padding,在Android Q以下版本也不会出问题。如果是代码中使用就需要做版本判断


<padding android:top="10dp" android:bottom="10dp" android:left="10dp" android:right="10dp"></padding>


闲话少叙,先看看最终的效果,下图左边是通过xml生成GradientDrawable,右边是通过代码生成GradientDrawable效果。


image.png

image.png

3. xml实现和代码实现



看下具体代码实现


  1. GradientDrawable xml实现


image.png


2. GradientDrawable代码实现


image.png

StateListDrawable xml实现

image.png

4. StateListDrawable 代码实现

image.png

addState(StatePressed)方法表示android:state_pressed="true"


minusState(StatePressed)方法表示android:state_pressed="false"


当然也可以添加多个状态


image.png


4. 特性以及源码



该库有以下特性:


  1. xml能实现的,它全部能实现
  2. 使用Builder模式,更容易构建Drawable
  3. 支持所有的android:state_xxx
  4. GradientDrawable,只要所有构建的参数内容一样(顺序可以打乱),内存中只会保留一份
相关文章
|
6月前
|
XML 存储 编解码
android 目录结构中 drawable(hdpi,ldpi,mdpi) 的区别
android 目录结构中 drawable(hdpi,ldpi,mdpi) 的区别
215 1
|
3月前
|
XML Android开发 数据格式
"探秘Android Drawable魔法:一篇文章教你玩转StateListDrawable与AnimationDrawable!"
【8月更文挑战第18天】Drawable是Android中用于屏幕绘制的图形对象,StateListDrawable与AnimationDrawable是两种实用类型。StateListDrawable可根据控件状态变化显示不同图形,如按钮的点击反馈;AnimationDrawable则用于实现帧动画效果,常用于加载提示或动态图标。两者均可通过XML定义或代码创建,并轻松应用于View的背景中,有效增强应用的交互性和视觉体验。
51 0
|
3月前
|
监控 Java 开发工具
### 绝招揭秘!Android平台GB28181设备接入端如何实现资源占用和性能消耗的极限瘦身?
【8月更文挑战第14天】本文介绍在Android平台优化GB28181标准下设备接入的性能方法,涵盖环境搭建、SDK集成与初始化。重点讲解内存管理技巧如软引用、按需加载资源,以及通过硬件加速解码视频数据和图像缩放来减轻CPU与GPU负担。同时采用线程池异步处理视频流,确保UI流畅性。这些策略有助于提高应用效率和用户体验。
44 0
|
5月前
|
XML Java API
54. 【Android教程】图片资源:Drawable
54. 【Android教程】图片资源:Drawable
75 0
|
6月前
|
Android开发
Android源代码定制:Overlay目录定制|调试Overlay资源是否生效
Android源代码定制:Overlay目录定制|调试Overlay资源是否生效
204 0
|
Java Android开发
Android 保存资源图片到相册最新写法适用于Android10.0及以上
Android 保存资源图片到相册最新写法适用于Android10.0及以上
810 0
|
编解码 监控 前端开发
Android平台GB28181设备接入端如何降低资源占用和性能消耗
Android平台GB28181设备接入端如何降低资源占用和性能消耗?
|
6月前
|
XML 编解码 Android开发
Android Studio App开发入门之图形定制Drawable的讲解及实战(附源码 超详细必看)
Android Studio App开发入门之图形定制Drawable的讲解及实战(附源码 超详细必看)
102 1
|
6月前
|
XML 编解码 Android开发
Android各种各样的Drawable-更新中
Android各种各样的Drawable-更新中
97 0
|
6月前
|
Android开发
[Android]Layer Drawable
[Android]Layer Drawable
47 0