RecyclerViewの使い方について初心者にわかりやすく、説明していきます。
RecyclerViewとは?
RecyclerViewとは、ListViewの進化版で、効率よく同じViewを作成することができる機能のことです。
動きとしては、画面内に表示されているレイアウトがスクロールによって画面外に行った時に、下から出てくるレイアウトはその画面外に行ったViewを再利用することで、効率の良い表示を行っています。
RecyclerViewの使い方
- gradle(:app)に依存関係を追加
- activity_main.xmlなどの表示させたいxmlファイルにrecyclerViewを追加
- データを用意
- アダプターを用意
- ビューホルダーを用意
- レイアウトマネージャーを用意
- 完成
よくわからないと思うので、実際に簡単なプロジェクトを使って理解していきます。
RecyclerViewの具体例
ここでは、ただTextViewを使って20個のデータを表示するアプリを作ってみます。
gradle(:app)に依存関係を追加
dependencies {
implementation 'androidx.appcompat:appcompat:1.5.1'
implementation 'com.google.android.material:material:1.7.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
//追加
implementation 'androidx.recyclerview:recyclerview:1.2.1'
}
//追加の下に書かれているコードをbuild.gradle(:app)ファイルに記入します。
activity_main.xmlなどの表示させたいxmlファイルにrecyclerViewを追加
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<!--RecyclerViewを使う上で必要な属性-->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/my_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
androidx.recyclerview.widget.RecyclerViewにデータが表示されます。
データを用意
表示したいデータを配列で用意します。
public class MainActivity extends AppCompatActivity {
//20個の要素を用意する
private final String[] dataset = new String[20];
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//RecycleViewの紐付け
RecyclerView recyclerView = findViewById(R.id.my_recycler_view);
//変更してもレイアウトサイズが変わらないことがわかっている場合、パフォーマンスを向上させるためにこの設定(レイアウトサイズを固定にする)をする。
recyclerView.setHasFixedSize(true);
//linear layout managerを使う
RecyclerView.LayoutManager rLayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(rLayoutManager);
int i = 0;
while (i < 20) {
//String.format(言語, 代入される文字列, %dに入れる数値)
dataset[i] = String.format(Locale.ENGLISH, "Dataの個数%d個目", i + 1);
i++;
}
MyAdapter adapter = new MyAdapter(dataset);
recyclerView.setAdapter(adapter);
}
}
これに対応してimport文も用意してください。
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.LinearLayoutManager;
import java.util.Locale;
作ってないファイルがまだあるので、作っていきます。
アダプターを用意
MyAdapterクラスを作ります。
![](https://androidblog.tokyo/wp-content/uploads/2022/11/スクリーンショット-2022-11-21-16.06.37-1024x277.png)
プロジェクトのcom.example.recyclerviewtestを右クリック。
![](https://androidblog.tokyo/wp-content/uploads/2022/11/スクリーンショット-2022-11-21-16.06.48-1024x212.png)
New→JavaClassをクリック。
![](https://androidblog.tokyo/wp-content/uploads/2022/11/スクリーンショット-2022-11-21-16.06.54-300x138.png)
Classが選択されている状態でMyAdapterと入力して完了してください。
そしてここにアダプターを作っていきます。
アダプターとは?
変換器具のことをアダプターと言いますが、そのままで、RecyclerViewを使うために必要な変換ファイルのことです。これがなければ、他のクラスで使うことができません。
今回はMainActivityに表示するTextViewに対するアダプターなので、例えば、ResultActivityを作って再度、RecyclerViewを使ってリスト表示をImageの羅列で表示するときは、ImageAdapter.javaのようなクラスをもう一度作ると言うことになります。
前提で押さえておきたいのが、アダプターを作る際に必ず書かないといけないメソッドが3つあります。
- onCreateViewHolderメソッド
- onBindviewHolderメソッド
- getItemCountメソッド
です。それぞれの説明は一度コードを書いてから説明します。
package com.example.recyclerviewtest;
import androidx.recyclerview.widget.RecyclerView;
import androidx.annotation.NonNull;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
//MainActivityからきたdatasetが渡される。
private final String[] localDataSet;
static class ViewHolder extends RecyclerView.ViewHolder {
private final TextView textView;
public ViewHolder(View view) {
super(view);
//textViewの紐付け
textView = view.findViewById(R.id.text_view);
}
public TextView getTextView() {
return textView;
}
}
//呼び出す時にここがよばれるからここで引数を渡す
public MyAdapter(String[] dataSet) {
this.localDataSet = dataSet;
}
//以下の3つの関数はレイアウトマネージャーから呼び出される。
//新しいViewHolderを作る必要がある度にこのonCreateViewHolderメソッドを呼び出す。
//Viewに対応するViewHolderを生成して返す。
@NonNull
@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
//リストアイテムのUIを定義する新しいViewを作る
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.my_text_view, viewGroup, false);
return new ViewHolder(view);
}
//Viewの内容を置き換える
//onBindViewHolderメソッドでデータを関連付ける。
//ViewHolderを使って、Viewの更新を行う。
@Override
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
//データセットからこの位置の要素を取得し、ビューの内容をその要素で置き換える。
//ここで、textViewの内容を代入している。
viewHolder.getTextView().setText(localDataSet[position]);
}
//MainActivityから受け取ったdatasetの数を返す
@Override
public int getItemCount() {
return localDataSet.length;
}
}
完成コード
//MainActivityからきたdatasetが渡される。
private final String[] localDataSet;
データを受け取る変数を用意します。
onCreateViewHolderメソッド
何やら、LayoutInflater.from(viewGroup.getContext())をviewに代入しています。
LayoutInflaterとは
inflaterとは、膨らませるの意味を持っています。
LayoutInflaterとは、指定したxmlのレイアウトリソースを利用できる仕組みです。
ですので、都度レイアウトをリストの行数に合わせて今回であれば、TextView()の文字を変えるために利用していると言えます。
getContext()とは
context自体が、一言で言うと、アプリに関する様々な要素へのアクセスを可能にしてくれるインターフェースのようです。
つまり、新しくViewを作っていくので、様々な要素に対してアクセスするから引数として渡しているのだと推測しています。
getContext()とは、そのViewが実行中になっているコンテキストを戻すようです。
なので、今回のTextView()を都度読み取ってくれているという認識であっていそうです。
最後に、新しくインスタンスをViewHolderclassで作って、新しいレイアウトを作っています。
まとめると、レイアウトのビューを作成するためにLayoutInflaterを使い、LayoutInflater.from()メソッドに対象となるコンテキスト(そのViewのインターフェース)を渡して、膨らませるLayoutInflaterを取得します。
onBindviewHolderメソッド
ViewHolderを用いて、Viewの更新を行います。
最初に表示されるときに呼ばれ、使いまわされる時にも呼び出されます。
引数にViewHolderとpositionがありますが、このViewHolderは先ほど説明したViewHolderとpositionでビューの位置を取得します。
その位置に対してデータを並べて表示していくので、localDataSet[position]としています。
getItemCountメソッド
これは、表示するためのデータの数を返します。
ビューホルダーを用意
先ほどから何度も出てきていますが、ViewHolderを作っていきます。
static class ViewHolder extends RecyclerView.ViewHolder {
private final TextView textView;
public ViewHolder(View view) {
super(view);
//textViewの紐付け
textView = view.findViewById(R.id.text_view);
}
public TextView getTextView() {
return textView;
}
}
ご自身で好きなViewHolderを作っていきます。
レイアウトマネージャーを用意
//linear layout managerを使う
RecyclerView.LayoutManager rLayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(rLayoutManager);
レイアウトマネージャーとは
一言で言うと、データをどのような並びで表示させるか決めるコードです。
LinearLayoutManagerだと、リストで今回でも使っている縦表示に表示できます。横にするには、thisの次の引数にLinearLayoutManager.HORIZONTALと指定します。
他にも、GridLayoutManagerがあります。
GridLayoutがあるので、使わないかもしれないですが、以下のような書き方です。
//5列の格子状に表示
val layouManager = GridLayoutManager(this, 5)
//5列で高さがバラバラな格子状に表示
val layoutManager = StaggeredGridLayoutManager(5, StaggeredGridLayoutManager.VERTICAL)
完成
実行して確認してみましょう。
このように表示されていたら完成です。
![](https://androidblog.tokyo/wp-content/uploads/2022/11/スクリーンショット-2022-11-22-13.58.18-181x300.png)
RecyclerViewまとめ
長く説明しましたが、プログラマーがやることは、onCreateViewHolder()でViewHolderインスタンスを生成し、onBindViewHolder()でその表示内容を更新するように考えて実装することです。
僕自身もまだ表面でしか理解できていないですが、更新しながら理解を深めていきたいと思います。