[Android]DataBindingを利用したRecyclerViewのセットアップ例

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

DataBindingを利用してRecyclerViewのセットアップやアダプターの実装をスッキリさせてみました。

リスト表示させるアイテムのレイアウトを用意

<?xml version="1.0" encoding="utf-8"?>
<layout
    xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable name="Item" type="sample.Item"/>
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/colorAccent"
        android:orientation="vertical">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:text="@{Item.getTitle()}"
            android:textAppearance="@style/TextAppearance.AppCompat.Title"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{Item.getMessage()}"
            android:textAppearance="@style/TextAppearance.AppCompat.Body1"/>

    </LinearLayout>

</layout>

アダプターを実装

ViewHolderには生成した専用のBindingクラスを渡すようにしています。 onBindViewHolderでsetしてviewへの反映が行われます。

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.BindingViewHolder> {

    private List<Item> mList;

    public CustomAdapter(List<Item> list) {
        mList = list;
    }

    @Override
    public BindingViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        ListItemBinding itemBinding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.list_item, parent, false);
        return new BindingViewHolder(itemBinding);
    }

    @Override
    public void onBindViewHolder(BindingViewHolder holder, int position) {
        holder.mItemBinding.setItem(mList.get(position));
    }

    @Override
    public int getItemCount() {
        return mList.size();
    }

    public static class BindingViewHolder extends RecyclerView.ViewHolder {

        private ListItemBinding mItemBinding;

        public BindingViewHolder(ListItemBinding dataBinding) {
            super(dataBinding.getRoot());
            mItemBinding = dataBinding;
        }
    }

}

BindingAdapterでRecyclerViewのdividerを用意

XMLでItemDecorationをセットできるようにAdapterクラスを作成します。 BindingAdapterを利用してXMLからカスタム属性にリソース等を渡せるようにします。

public class RecyclerViewBindingAdapter {

    @BindingAdapter("divider")
    public static void setDividerDrawable(RecyclerView recyclerView, Drawable drawable) {
        // 適当なItemDecorationを用意
        recyclerView.addItemDecoration(new DividerItemDecoration(drawable));
    }
}

こちらは以下の記事を参考にさせて頂きました。
RecyclerViewのdividerをDataBindingで設定する

RecyclerViewをセットアップ

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

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <include layout="@layout/toolbar"/>

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler"
            style="@style/RecyclerView.Linear"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:dividerDrawable="@{@drawable/divider}"/>

    </LinearLayout>

</layout>

レイアウトが動的に変わったりしないのであれば、LayoutManagerもstyleに定義しておき、XMLで指定します。

<resources>
    <style name="RecyclerView">
        <item name="android:clipToPadding">false</item>
        <item name="android:clipChildren">false</item>
        <item name="android:scrollbarStyle">outsideOverlay</item>
    </style>

    <style name="RecyclerView.Linear">
        <item name="android:orientation">vertical</item>
        <item name="layoutManager">android.support.v7.widget.LinearLayoutManager</item>
    </style>

    <style name="RecyclerView.Grid">
        <item name="layoutManager">android.support.v7.widget.GridLayoutManager</item>
    </style>
</resources>

LayoutManagerやItemDecorationをここまでで設定できたので、コード側がすこしシンプルになりました

public class MainActivity extends AppCompatActivity {

    private List<Item> mData = new ArrayList<>();

    @BindView(R.id.recycler)
    RecyclerView mRecyclerView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        addList();
        CustomAdapter adapter = new CustomAdapter(mData);
        mRecyclerView.setAdapter(adapter);
    }

    private void addList() {
        // データを追加
    }
}

まとめ

DataBindingを利用することで動的なViewの変化も半自動的に行えたりするので、まかせられる所は積極的に使っていけそうです。