Androidアプリ開発 RecyclerViewで一覧画面を作成する

2016年04月05日(編集2016年04月30日)
このエントリーをはてなブックマークに追加

Androidアプリで一覧データのUI(ユーザーインターフェース)を作成する場合は、ListViewかRecyclerViewを使います。この記事は、RecyclerViewの使い方を記載した記事です。

環境はAndroid 6.0 (API level 23) です。

環境

  • Android Studio 1.5.1
  • android sdk 23
  • Build Tools, Revision 23.0.3
  • support recyclerview 23.3.0

難易度

初心者向け

サンプルコード

https://github.com/java-lang-programming/Android-RecyclerView-Demo

RecyclerViewとは

RecyclerViewクラスは、Androidアプリで一覧画面のUIを作成する時に利用します。

RecyclerViewで作成した一覧画面

ListViewとの違い

一覧画面のUIは、ListViewクラスを利用しても作成できます。
ListViewクラスはAndroidの初期から用意されているクラスです。
シンプルな一覧画面(少なめのデータの一覧表示、クリック遷移)なら、ListViewで十分に機能を満たせます。

ListViewで作成した一覧画面。左が一覧表示。右はクリック時

一方で、RecyclerViewは、一覧画面のUIで様々なアクションを利用したい場合に使います。
例えば、スワイプ、ドラッグ&ドロップ、一覧の各データごとにUIを加工する場合は、RecyclerViewを利用します。

RecyclerViewで作成した一覧画面。スワイプ実行時

機能比較

一覧画面でよく利用する機能を比較した表を示します。

■ ListViewとRecyclerViewの機能比較一覧

機能 ListView RecyclerView
header ×
footer ×
項目クリック 実装する
区切り線 実装する
スワイプ ×
ドラッグ&ドロップ ×
横スクロール ×
キャッシュ(ViewHolder) ×

実装の難易度はListViewよりRecyclerViewのほうが高いです。
RecyclerViewは、ListViewの仕組みを理解している前提で実装することになります。

どちらを使うか迷った場合、データよりアクションに重きを置く場合は、RecyclerViewを利用するべきです。

ただし、Androidアプリ開発初心者の場合は、ListViewの方がわかりやすいです。
なので、最初はListViewで一覧画面を作成し、実装に慣れてきたらRecyclerViewに移行するのが現実的な方法です。

ライブラリインストール

RecyclerViewを使う場合は、ライブラリをインストールする必要があります。
ライブラリの導入にはgradleを使います。

{project_folder}/app/build.gradle
dependencies {
    compile 'com.android.support:recyclerview-v7:23.3.0'
}
        

RecycleView

実際にRecyclerViewを使用してアプリのサンプルを作成していきます。Android Studio(1.5.1)を利用している場合は、GUIから雛形を作成できます。

作成手順は、javaクラスを作成したいフォルダを選択し、New → Fragment → Fragment(List)です。

コードの解説

Android Studioで自動生成されたコードでRecycleViewの説明をします。
RecycleViewは、以下のクラスやインターフェースを組み合わせて作成します。

■ RecyclerViewで利用するインターフェースとクラスの一覧

名称 機能
RecyclerView 巨大な量の情報を、制限された画面上で柔軟に表示する
RecyclerView.Adapter RecyclerView内で表示するデータと画面を結合する
RecyclerView.ViewHolder viewの項目のデータを扱う
RecyclerView.LayoutManager RecyclerView内の項目の位置と計算をおこなう
ItemTouchHelper RecyclerViewでスワイプやドラッグ&ドロップを可能にする
RecyclerView.ItemDecoration viewのレイアウトを編集します

RecycleViewの定義

RecyclerViewをxmlで定義します。android.support.v7.widget.RecyclerViewのタグを記述します。

{project_folder}/app/res/layout/fragment_item_list.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView 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"
    android:id="@+id/recyclerView"
    android:name="com.java_lang_programming.android_recycleview_demo.ui.RecyclerViewFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginLeft="16dp"
    android:layout_marginRight="16dp"
    app:layoutManager="LinearLayoutManager"
    tools:context="com.java_lang_programming.android_recycleview_demo.ui.RecyclerViewFragment"
    tools:listitem="@layout/fragment_item" />
        

xmlで記載したtagは、java側で実体化します。

{project_folder}/app/com/ui/RecyclerViewFragment.java
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_item_list, container, false);

        // Set the adapter
        if (view instanceof RecyclerView) {
            Context context = view.getContext();
            RecyclerView recyclerView = (RecyclerView) view;
            recyclerView.setLayoutManager(new LinearLayoutManager(context));
            recyclerView.setAdapter(new MyItemRecyclerViewAdapter(DummyContent.ITEMS, mListener));
        }
        return view;
    }
        

実装ポイントの解説

  • View生成
View view = inflater.inflate(R.layout.fragment_item_list, container, false);
        

inflateメソッドで、fragment_item_listのlayoutをviewオブジェクトとして取得します。
第3引数のattachToRootは、ほとんどの場合falseにして使います。

  • RecyclerView.LayoutManager設定
recyclerView.setLayoutManager(new LinearLayoutManager(context));
        

setLayoutManagerメソッドで、RecyclerViewで使うLinearLayoutManagerを設定します。LinearLayoutManagerは、縦のレイアウトを生成します。UIは、ListViewと同じ縦の一覧表示です。

  • RecyclerView.Adapter設定
recyclerView.setAdapter(new MyItemRecyclerViewAdapter(DummyContent.ITEMS, mListener));
        

setAdapterメソッドで、RecyclerViewで表示するデータをviewと関連づけることができます。MyItemRecyclerViewAdapterを設定しています。MyItemRecyclerViewAdapterは、RecyclerView.Adapterを継承したクラスです。

RecyclerView.Adapterの定義

RecyclerViewでは、RecyclerView.Adapterを介して表示データを扱います。

RecyclerView.Adapterはabstractクラスです。abstractクラスは、抽象メソッドが宣言されています。抽象メソッドは、実装なしで宣言されているメソッドのことです。メソッドは以下のとおりです。

android.support.v7.widget.RecyclerView.java#Adapter
public abstract VH onCreateViewHolder(ViewGroup parent, int viewType);

public abstract void onBindViewHolder(VH holder, int position);
        

RecyclerView.Adapterのサブクラスは、 onCreateViewHolder, onBindViewHoldermmwメソッドを実装しないといけません。

以下のように実装します。

{project_folder}/app/com/ui/MyItemRecyclerViewAdapter.java
public class MyItemRecyclerViewAdapter extends RecyclerView.Adapter<MyItemRecyclerViewAdapter.ViewHolder> {

    private final List<DummyItem> mValues;
    private final OnListFragmentInteractionListener mListener;

    public MyItemRecyclerViewAdapter(List<DummyItem> items, OnListFragmentInteractionListener listener) {
        mValues = items;
        mListener = listener;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.fragment_item, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(final ViewHolder holder, int position) {
        holder.mItem = mValues.get(position);
        holder.mIdView.setText(mValues.get(position).id);
        holder.mContentView.setText(mValues.get(position).content);

        holder.mView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (null != mListener) {
                    // Notify the active callbacks interface (the activity, if the
                    // fragment is attached to one) that an item has been selected.
                    mListener.onListFragmentInteraction(holder.mItem);
                }
            }
        });
    }

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

    public class ViewHolder extends RecyclerView.ViewHolder {
        public final View mView;
        public final TextView mIdView;
        public final TextView mContentView;
        public DummyItem mItem;

        public ViewHolder(View view) {
            super(view);
            mView = view;
            mIdView = (TextView) view.findViewById(R.id.id);
            mContentView = (TextView) view.findViewById(R.id.content);
        }

        @Override
        public String toString() {
            return super.toString() + " '" + mContentView.getText() + "'";
        }
    }
}
        

実装ポイントの解説

  • RecyclerView.ViewHolder生成
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.fragment_item, parent, false);
    return new ViewHolder(view);
}
        

抽象メソッドを継承したonCreateViewHolderメソッドは、ViewHolderを返します。
ViewHolderはview項目のデータを扱うクラスです。
inflateで生成したviewオブジェクトをViewHolderのコンストラクタに設定します。

  • ViewHolderの具体的な処理
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
    holder.mItem = mValues.get(position);
    holder.mIdView.setText(mValues.get(position).id);
    holder.mContentView.setText(mValues.get(position).content);

    holder.mView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (null != mListener) {
                // Notify the active callbacks interface (the activity, if the
                // fragment is attached to one) that an item has been selected.
                mListener.onListFragmentInteraction(holder.mItem);
            }
        }
    });
}
        

抽象メソッドを継承したonBindViewHolderは、特定の位置(position)のデータを表示するためにRecyclerViewに呼ばれます。
ViewHolderオブジェクトにアクセスして、データの設定やクリック処理を記述します。

  • RecyclerView.Adapter継承クラス

MyItemRecyclerViewAdapterクラスは、RecyclerView.Adapterの継承クラスです。

RecyclerView.Adapterは、ジェネリクスで<VH extends ViewHolder>と宣言しているので、RecyclerView.ViewHolderを継承したクラスになります。

RecyclerView.ViewHolderクラスもabstractクラスです。
MyItemRecyclerViewAdapterクラス内で、public class ViewHolder extends RecyclerView.ViewHolderとしてサブクラスを作成しています。

コードで考えると複雑になって理解しにくいです。以下の様な図を頭にイメージすると良いと思います。

コードのUML関連図

ビルドして実行

実装を終えたら、ビルドしてアプリを実行します。

ビルドしてアプリ立ち上げ

一覧UIが表示されました。

まとめ

RecyclerViewは、ListViewと比較すると、実装が複雑です。敬遠する人も多いとおもいます。

RecyclerViewを利用する時に大切なことは、それぞれのクラスが担当しているオブジェクトや操作をイメージで掴むことです。

抽象クラスやインターフェースが多いので、Javaに慣れていないと理解に時間がかかるとも思います。ただ、Androidのコーディングに慣れるには絶好のライブラリです。

作れるアプリの幅も広がると思うので、是非挑戦してください。

関連記事

タグ検索で調べてみよう

Android6.0 UI