Epoxy
Epoxy通过声明式的方式帮助RecyclerView更高效的实现数据加载、UI更新等逻辑,提高列表场景的开发效率。
https://github.com/airbnb/epoxy Epoxy is an Android library for building complex screens in a RecyclerView - airbnb/epoxy
开发流程
Epoxy的基本使用流程:
创建cell的layout文件 可以使用.xml、或者 .kt创建cell的layout。推荐使用xml,搭配databinding使用起来更简单。根据cell生成EpoxyModel 在package-info.java中声明layout文件、kapt根据xml自动生成EpoxyModel代码,供EpoxyRecyclerView使用创建EpoxyController EpoxyController相当于RecyclerView的Adapter,用来将数据绑定到UI,同时定义OnClick等事件使用EpoxyController 将EpoxyController设置到EpoxyRecyclerView,完成列表的数据记载和显示
接下来简单介绍一下每一步的具体实现。例如我们需要在列表中加载下列数据:
data class Foo (
var title
: String
,
var bar
: List
<Bar
>
)
data class Bar (
var body
: String
,
var time
: String
)
0. gradle
apply plugin
: 'kotlin-kapt'
android
{
dataBinding
{
enabled
= true
}
}
kapt
{
correctErrorTypes
= true
}
dependencies
{
implementation
'com.airbnb.android:epoxy:3.4.2'
kapt
'com.airbnb.android:epoxy-processor:3.4.2'
implementation
'com.airbnb.android:epoxy-databinding:3.4.2'
}
1. cell layout
list_cell_a.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
>
<data>
<variable
name="title"
type="String"
/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{title}"
android:textSize="24sp"
android:textStyle="bold"
tools:text="test"
/>
</LinearLayout>
</layout>
list_cell_b.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
>
<data>
<variable
name="body"
type="String"
/>
<variable
name="time"
type="String"
/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="8dp"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{body}"
android:textSize="20sp"
tools:text="test"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{time}"
android:textSize="18sp"
tools:text="test"
/>
</LinearLayout>
</layout>
2. package-info.java
@EpoxyDataBindingLayouts({
R
.layout
.list_cell_a
,
R
.layout
.list_cell_b
})
package com
.airbnb
.epoxy
.sample
;
import com
.airbnb
.epoxy
.EpoxyDataBindingLayouts
;
编译后,会根据layout文件,生成EpoxyModels代码,例如ListCellABindingModel_、ListCellBindingModel_等,用来绑定数据
3. EpoxyController
继承TypedEpoxyController,重写buildmodels,用声明式的方式填充UI的数据。
class FooBarController
: TypedEpoxyController
<Foo
>() {
override fun buildModels(foo
: Foo
) {
ListCellABindingModel_()
.title(foo
.title
)
.id(modelCountBuiltSoFar
)
.addTo(this)
foo
.bar
.forEach {
ListCellBindingModel_()
.body(it
.body
)
.time(it
.time
)
.id(modelCountBuiltSoFar
)
.addTo(this)
}
}
}
根据buildModels参数个数选择不同基类,例如Typed2EpoxyController、Typed3EpoxyController等title、body、time是layout的定义的databindingid用来区分不同类型的Cell,所有的EpoxyModels必须有唯一id
4. use in RecyclerView
class FooBarFragment
: Fragment() {
lateinit var binding
: FragmentFooBarBinding
override fun onCreateView(inflater
: LayoutInflater
?, container
: ViewGroup
?, savedInstanceState
: Bundle
?): View
? {
binding
= DataBindingUtil
.inflate(inflater
, R
.layout
.fragment_foo_bar
, container
, false)
return binding
.root
}
override fun onActivityCreated(savedInstanceState
: Bundle
?) {
super.onActivityCreated(savedInstanceState
)
val controller
= FooBarController()
binding
.recyclerView
.adapter
= controller
.adapter
val data = Foo("title", listOf(Bar("str1","time1"),Bar("str2","time2")))
controller
.setData(data)
})
}
通过Controller中设置data,数据将自动在渲染到列表中
总结
通过简单的实例,可以感觉到Epoxy有以下几个好处
避免了ViewHolder的使用, 代码更少通过EpoxyController和EpoxyModel,声明式的填充数据到UI,简单直观每次数据更新后,会自动diff最小量刷新UI(类似pagging的功能)配合MvRx使用,实现完整的响应式UI