Kotlin开发Android自定义组件:用data class还是setter设置属性?
Android自定义组件属性设置的最佳实践
先聊聊两种方式的痛点
- Data Class:纯数据载体,没法自动触发View的UI更新或状态同步;如果组件属性之间有依赖逻辑,批量赋值时没法逐个处理;也没法和View的生命周期绑定,比如属性变化需要在
onMeasure前生效的场景,data class做不到。 - Setter/Getter:属性多了之后代码会变得臃肿,每个属性都要写一套set/get;批量设置属性时得挨个调用set方法,不够高效;也没法快速做属性的批量校验或备份。
最佳实践:两者结合,互补使用
完全可以同时用两种方式,这也是Android自定义组件开发里的常见方案:
1. Setter/Getter作为核心控制方式
对于需要和View状态、UI更新绑定的单个属性,优先用setter/getter,在set方法里直接处理属性变化后的逻辑,比如触发重绘、重新测量:
class CustomView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : View(context, attrs, defStyleAttr) { private var _textColor: Int = Color.BLACK var textColor: Int get() = _textColor set(value) { if (_textColor != value) { _textColor = value invalidate() // 立即触发UI重绘 } } private var _textSize: Float = 14f var textSize: Float get() = _textSize set(value) { if (_textSize != value) { _textSize = value requestLayout() // 触发重新测量布局 } } }
这种方式符合Android View体系的设计习惯,能保证属性变化后View状态的一致性。
2. Data Class作为批量配置的辅助
定义一个纯数据的data class来封装所有可配置属性,再给View加一个setConfig方法,实现批量赋值:
// 纯数据配置类,只存属性值 data class CustomViewConfig( val textColor: Int = Color.BLACK, val textSize: Float = 14f, val padding: Int = 8 ) class CustomView(...) : View(...) { // ...上面的单个属性setter/getter fun setConfig(config: CustomViewConfig) { // 利用单个属性的setter自动处理状态更新 this.textColor = config.textColor this.textSize = config.textSize this.setPadding(config.padding, config.padding, config.padding, config.padding) // 也可以统一触发一次更新,减少多次invalidate的开销 // invalidate() } }
使用的时候还能借助data class的copy方法快速生成修改后的配置:
val defaultConfig = CustomViewConfig() val redTextConfig = defaultConfig.copy(textColor = Color.RED) customView.setConfig(redTextConfig)
注意事项
- 不要让data class持有View的引用,避免内存泄漏,它只负责存储纯数据。
- 如果属性之间有依赖关系,在
setConfig里要注意赋值顺序,比如先设置尺寸相关属性,再设置位置相关的。 - 单个属性的setter里最好加个值判断,避免重复赋值导致不必要的UI更新。
内容的提问来源于stack exchange,提问作者Hussam
相关产品推荐
相关产品推荐

