[Android] RecyclerViewを実装する

訳あって、久しぶりにJavaを書いています。Javaの書き方を思い出しながら、RecyclerViewを実装してみました。RecyclerViewはそこそこの頻度で使うのに空で実装できないので、ここにその実装方法を記録しておきます。早速、やっていきます。

まずはプロジェクトでRecyclerViewを使えるようにします。app/build.gradleにRecyclerViewの設定を追加しましょう。ついでにButterKnifeも使いたいので、ButterKnifeの設定も合わせて追加しました。

dependencies {
    // Recycler View
    implementation 'com.android.support:recyclerview-v7:28.0.0'

    // ButterKnife
    implementation 'com.jakewharton:butterknife:10.1.0'
    annotationProcessor 'com.jakewharton:butterknife-compiler:10.1.0'
}

次に、ActivityのレイアウトファイルにRecyclerViewを追加します。ここは特に難しくありませんが、必ずRecyclerViewにidを割り振っておきましょう。後で使います。

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".activity.GameActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

RecyclerViewで表示する個々のレイアウトを作成します。ここではTextViewを一つのみ持つレイアウトを定義しています。

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

上記のレイアウトに対応するエンティティを定義します。Kotlinを使えばデータクラスを使ってイケてる感じに実装できるんですが、Javaなので…。

public class Action {
    private String action;

    public Action(String message) {
        this.action = action;
    }

    public String getAction() {
        return action;
    }

    public void setAction(String action) {
        this.action = action;
    }
}

ViewHolderを実装します。個々の項目のViewを保持する役目を持つクラスですね。今回は、Activity内にstaticクラスとして定義しました。クラスを分割する方法もあると思いますが、このViewHolderはこのActivityでしか使いませんのでstaticクラスでもいいかなと思います。また、ここでもViewの参照を取得するためにButterKnifeを使っています。あとは特に難しいことはないですね。

static class ViewHolder extends RecyclerView.ViewHolder {

    @BindView(R.id.text_view) TextView textView;

    ViewHolder(@NonNull View itemView) {
        super(itemView);

        ButterKnife.bind(this, itemView);
    }
}

ViewAdapterを実装します。こちらもActivity内にstaticクラスとして定義しました。ここに示してあるのは最低限の実装になるかと思います。

static class ViewAdapter extends RecyclerView.Adapter<ViewHolder> {

    private List<Action> list;

    ViewAdapter(List<Action> list) {
        this.list = list;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_action, parent, false);

        return new ViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        holder.textView.setText(list.get(position).getAction());
    }

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

ここまで来たら、Activity内でRecyclerViewを表示する処理を書いていきます。RecyclerViewへの参照はButterKnifeで取得しています。データを保持するリストの実装は適当です。このリストへの参照をViewAdapterに渡して、RecyclerViewにセットすればOKですね。また、RecyclerViewのレイアウトを決めるLayoutManagerにはLinearLayoutManagerを使っています。LinearLayoutManagerは、デフォルトでは縦方向にレイアウトを並べる設定になるかと思います。また、setHasFixedSizeをtrueに設定して、同じ高さのレイアウトを再利用しますよ、と伝えてあげます。この設定でパフォーマンスが改善されるようです。

@BindView(R.id.recycler_view) RecyclerView recyclerView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_game);
    ButterKnife.bind(this);

    // TODO
    List<Action> list = new ArrayList<>();
    for (int i = 0; i < 100; i++) {
        Action action = new Action("action: " + i);
        list.add(action);
    }

    ViewAdapter adapter = new ViewAdapter(list);
    recyclerView.setAdapter(adapter);

    LinearLayoutManager layoutManager = new LinearLayoutManager(this);
    recyclerView.setLayoutManager(layoutManager);

    recyclerView.setHasFixedSize(true);
}

以上でRecyclerViewの実装ができました。やりたいことの割に実装が多くて大変なのですが、もうちょっと簡単にならないでしょうか。