LoginSignup
27
23

More than 5 years have passed since last update.

RecyclerViewの実装が楽になるEpoxyライブラリを使ってみる

Last updated at Posted at 2017-12-09

概要

EpoxyはAirbnb製のライブラリである。特に、複数のViewTypeを持つタイプのRecyclerViewの実装が楽になる。

導入

build.gradleに以下を追加。

apply plugin: 'kotlin-kapt'

dependencies {
    // epoxy
    compile 'com.airbnb.android:epoxy:2.7.3'
    kapt 'com.airbnb.android:epoxy-processor:2.7.3'
    compile 'com.airbnb.android:epoxy-databinding:2.7.3'

}

kapt {
    correctErrorTypes = true
}

レイアウト

RecyclerViewを使用してheader2種類、contents2種類の計4種類のレイアウトが含まれた以下のような画面を作成する。

device-2017-12-09-110718.png

Epoxyを使わない方法だと、RecyclerViewに紐付けるAdapter内で4種類のViewTypeに応じて処理を分けるような実装が必要になると思われる。

メインのレイアウト

<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler_view"
            app:layoutManager="android.support.v7.widget.LinearLayoutManager"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </RelativeLayout>

</layout>

header1のレイアウト

<layout xmlns:android="http://schemas.android.com/apk/res/android" >

    <data>
        <variable name="title" type="String" />
    </data>

    <LinearLayout
        android:background="#ff0000"
        android:gravity="left|center_vertical"
        android:layout_width="match_parent"
        android:layout_height="100dp">

        <TextView
            android:text="@{title}"
            android:textStyle="bold"
            android:layout_marginLeft="20dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </LinearLayout>

</layout>

header2のレイアウト

<layout xmlns:android="http://schemas.android.com/apk/res/android" >

    <data>
        <variable name="title" type="String" />
    </data>

    <LinearLayout
        android:background="#00ff00"
        android:gravity="right|center_vertical"
        android:layout_width="match_parent"
        android:layout_height="80dp">

        <TextView
            android:text="@{title}"
            android:textStyle="italic"
            android:layout_marginRight="20dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </LinearLayout>

</layout>

contents1のレイアウト

<layout xmlns:android="http://schemas.android.com/apk/res/android" >

    <data>
        <variable name="text" type="String" />
    </data>

    <LinearLayout
        android:gravity="center"
        android:background="#eeeeee"
        android:layout_width="match_parent"
        android:layout_height="50dp">

        <TextView
            android:text="@{text}"
            android:textSize="35sp"
            android:layout_gravity="center"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </LinearLayout>

</layout>

contents2のレイアウト

<layout xmlns:android="http://schemas.android.com/apk/res/android" >

    <data>
        <variable name="text" type="String" />
    </data>

    <LinearLayout
        android:gravity="center"
        android:background="#888888"
        android:layout_width="match_parent"
        android:layout_height="50dp">

        <TextView
            android:text="@{text}"
            android:textSize="18sp"
            android:fontFamily="serif-monospace"
            android:textColor="#ffffff"
            android:layout_gravity="center"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </LinearLayout>

</layout>

package-info.java

EpoxyにレイアウトファイルからBindingModel_クラスを自動生成してもらうために、package-info.javaを作成し、以下のように記述する。

@EpoxyDataBindingLayouts({
        R.layout.header1,
        R.layout.header2,
        R.layout.contents1,
        R.layout.contents2
})
package example.test.epoxytest;

import com.airbnb.epoxy.EpoxyDataBindingLayouts;

作成したpackage-info.javaは以下のように配置する。
スクリーンショット 2017-12-09 11.33.01.png

ここまで作成したら、一旦ビルドすることでHeader1BindingModel_, Contents1BindingModel_, Header2BindingModel_, Contents2BindingModel_がEpoxyによって自動生成される。

Dataクラス作成

コンテンツのデータを格納するクラスを作成する。

class Data(val header1: String, val contents1: List<String>, val header2: String, val contents2: List<String>)

Controller作成

Adapterの代わりにControllerを作成する。

class TestController : TypedEpoxyController<Data>() {

    override fun buildModels(data: Data) {

        Header1BindingModel_()
                .title(data.header1)
                .id(modelCountBuiltSoFar)
                .addTo(this)

        for (item in data.contents1) {
            Contents1BindingModel_()
                    .text(item)
                    .id(modelCountBuiltSoFar)
                    .addTo(this)
        }

        Header2BindingModel_()
                .title(data.header2)
                .id(modelCountBuiltSoFar)
                .addTo(this)

        for (item in data.contents2) {
            Contents2BindingModel_()
                    .text(item)
                    .id(modelCountBuiltSoFar)
                    .addTo(this)
        }
    }
}

Adapterを実装するのと比べると簡潔である。

MainActivity

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)

        val controller = TestController()
        controller.setData(Data("header1", listOf("aa", "ab", "ac"),
                "header2", listOf("ba", "bb", "bc", "bd", "be", "bf")))
        binding.recyclerView.adapter = controller.adapter

        binding.recyclerView.addItemDecoration(DividerItemDecoration(this, DividerItemDecoration.VERTICAL))
    }
}

ControllerにDataを設定し、Controller内部で生成されたadapterをRecyclerViewに紐付ける。

まとめ

Epoxyを使うことでボイラープレートコードが減り、少ない記述で複数のviewTypeを持つRecyclerViewの実装ができた。:ok_woman_tone2:

68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3134313933372f32323438323538662d613565362d376637302d643165312d3666313930396438646333642e706e67.png

27
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
23