本文已参与「新人创作礼」活动,一起开启掘金创作之路。
Kotlin Model 例子
Epoxy Model 可以用 Kotlin 很容易地写出来. 在 Kotlin 中推荐使用@ModelView或者ViewHolder途径 - 如果是自定义视图或者有更复杂的视图的话, 要使用@ModelView.
本页假设你已经理解了Epoxy. 这只会在Kotlin使用的不同之处添加额外的上下文.
这里是用Kotlin写 Model 的一些想法. 自己也可以适配这些想法并创建自己的模型. 要查看更多代码, 可以查看Kotlin Model 例子.
使用@ModelView
ModelView注解用在View上, 并从 View 上生成 Model. 这在Kotlin中非常简单, 但属性需要一些特殊处理.
@ModelView(autoLayout = ModelView.Size.MATCH_WIDTH_WRAP_HEIGHT)
class KotlinView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
@ModelProp
fun setValue(value: Int) {
// Do something here with value
}
// Or if you need to store data in properties there are two options
// Can make it nullable like this and annotate the setter
var myListener: View.OnClickListener? = null
@CallbackProp set
// Or use lateinit
@TextProp lateinit var myText: CharSequence
@AfterPropsSet
fun useProps() {
// This is optional, and is called after the annotated properties above are set.
// This is useful for using several properties in one method to guarantee they are all set first.
}
}
使用View Holder
这种更传统的风格使用了Epoxy view holder pattern. KotlinHolder用于缓存视图的查询, 并且使用属性委托来简化这个过程.
该注解允许生成子类, 该子类有equals/hashcode和一些其它的辅助. 也生成了扩展函数以使在EpoxyController中更容易使用 ViewHolder.
Holder代码用一个例子来提供, 可以拷贝到项目中并按需修改.
@EpoxyModelClass(layout = R.layout.view_holder_page_header)
abstract class SampleKotlinModelWithHolder : EpoxyModelWithHolder<Holder>() {
@EpoxyAttribute lateinit var title: String
@EpoxyAttribute lateinit var imageUrl: Uri
override fun bind(holder: Holder) {
holder.imageView.setImageURI(imageUrl)
holder.titleView.text = title
}
}
class Holder : KotlinHolder() {
val titleView by bind<TextView>(R.id.title)
val imageView by bind<ImageView>(R.id.image)
}
自定义Kotlin Model
官方未支持
这种方法使用了更加理想化的 Kotlin 方法, 并且不需要注解或者注解处理. 数据类用于生成 Epoxy 需要用来 diffing 的equals/hashcode方法. 通过属性代理View可以在 Model 中很容易地声明, 所以 View Holder也不需要了.
缺陷是视图会在每一次 Model 绑定到 View 时再次进行查询, 所以这并不很高效. 所以, 对于性能要求高的应用, 自定义 Kotlin Model 是不推荐的, 只是用于一个起点或者想法, 可能之后你想要进行适配.
如果你并不十分理解Epoxy, 或者不十分理解Kotlin, 以致不知道这个代码是干嘛的, 那么推荐你使用@ModelView或者ViewHolder方式.
基于KotlinModel例子, 你可以拷贝进项目然后适配.
缺点是你会丢失生成代码提供的一些功能(如用于EpoxyController的扩展功能)
data class SampleKotlinModel(
val title: String,
val imageUrl: Uri
) : KotlinModel(R.layout.view_holder_page_header) {
val titleView by bind<TextView>(R.id.title)
val imageView by bind<ImageView>(R.id.image)
override fun bind() {
titleView.text = title
imageView.setImageURI(imageUrl)
}
}