📌 Intro
이전에 정리한 ListView는 항목이 갱신될 때마다 매번 아이템 뷰를 새로 구성해야 한다. 이것은 많은 데이터를 표시하는데 있어 성능 저하를 유발할 수 있다. 이를 해결하기 위해 나온 RecyclerView는 아이템을 표시하기 위해 뷰를 재활용하고, 이를 위해 뷰홀더(ViewHolder)패턴을 사용하도록 만들어져있다.
ListView는 기본적으로 아이템들을 수직 방향으로만 나열할 수 있다. 그리고 아이템 뷰를 동적으로 구성하기 어려웠다.
이에 비해 RecyclerView는 수직, 수평 방향으로 아이템들이 나열되게 만들 수 있고, 아이템 뷰의 동적 구성을 용이하게 해주며 이를 런타임에 바꿀 수도 있다.
그러면 RecyclerView에 대해 더 자세히 알아보고 어떻게 사용할 수 있는지에 대해 알아보도록 하자.
📌 RecyclerView?
앞에서 ListView와 차이점을 설명하면서 RecyclerView의 특성에 대해 설명했기 때문에 간단하게 정리하도록 하겠다.
RecyclerView는 사용자가 관리하는 많은 데이터의 집합을 개별 아이템 단위로 구성하여 화면에 출력하는 뷰그룹이며, 한 화면에 표시되기 힘든 많은 수의 데이터를 스크롤이 가능한 리스트로 표시해주는 위젯이다.
RecyclerView는 ListView와 사용 목적 및 동작 방식이 유사하지만, RecyclerView가 더 좋은 성능을 가지고 있다고 생각할 수 있다.
📌 RecyclerView를 위한 구성 요소
RecyclerView는 데이터 목록을 아이템 단위의 뷰로 구성하여 화면에 표시하기 위해 Adapter를 사용한다. (이는 ListView와 같다.)
또, 리사이클러뷰는 다양한 형태의 레이아웃으로 아이템 뷰를 나열할 수 있다. 이를 위해 아이템 뷰가 나열되는 형태를 관리하기 위한 요소를 제공하는데, 이를 레이아웃 매니저라고 한다.
마지막으로 레이아웃 매니저가 제공하는 레이아웃 형태로 어댑터를 통해 만들어진 각 아이템 뷰는 뷰홀더 객체에 저장되어 화면에 표시되고, 필요에 따라 생성 또는 재활용한다.
- 리사이클러뷰의 구성요소 및 처리 구조(https://recipes4dev.tistory.com/154)
- RecyclerView
사용자 데이터를 리스트 형태로 화면에 표시하는 컨테이너 역할 - Adapter
RecyclerView에 표시될 아이템 뷰를 생성하는 역할(사용자 데이터 리스트로부터 아이템 뷰를 생성한다.) - Layout Manager
RecyclerView가 아이템을 화면에 표시할 때 아이템 뷰들이 RecyclerView내부에 배치되는 형태를 관리한다. - ViewHolder
화면에 표시될 아이템 뷰를 저장하는 객체로, Adapter에 의해 관리된다.
미리 생성된 뷰홀더 객체가 있는 경우 새로 생성하지 않고 이미 만들어져 있는 뷰홀더를 재활용하는데, 이 때는 단순히 데이터가 뷰홀더의 아이템 뷰에 바인딩된다.
📌 RecyclerView 사용방법
그럼 이제 RecyclerView의 사용방법에 대해 알아보자.
1. Activity에 RecyclerView 추가하기
activity_main.xml 파일(레이아웃)에 RecyclerView를 추가한다.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
2. RecyclerView 아이템 뷰 레이아웃 추가하기
RecyclerView 아이템에 표시될 아이템 뷰 레이아웃을 추가한다.
예제로 작성하는 것이기 때문에 아이템 뷰는 간단하게 텍스트 뷰 위젯 하나만 가진다.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
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"
android:layout_weight="1"
android:text="TextView" />
</LinearLayout>
3. RecyclerView의 Adpater 구현하기
ListView의 경우 보통 BaseAdapter클래스를 상속 받아 Adapter를 만들었지만 RecyclerView에서는 개발자가 Adapter를 직접 구현해야 한다. 그리고 이 때 만드는 Adapter는 RecyclerView.Adapter를 상속하여 구현해야 한다.
RecyclerView.Adapter 를 상속 받아 새로운 Adapter를 구현할 때 오버라이드가 필요한 메서드는 다음과 같다.
- onCreateViewHolder(ViewGroup parent, int viewType)
viewType 형태의 아이템 뷰를 위한 뷰홀더 객체 생성 - onBindViewHolder(ViewHolder holder, int position)
position에 해당하는 데이터를 뷰홀더의 아이템뷰에 표시 - getItemCount()
전체 아이템 개수 리턴
package com.example.recyclerview;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class SimpleTextAdapter extends RecyclerView.Adapter<SimpleTextAdapter.ViewHolder> {
private ArrayList<String> items = null;
public class ViewHolder extends RecyclerView.ViewHolder{
TextView textView;
ViewHolder(View itemView){
super(itemView);
// 뷰 객체에 대한 참조
textView = itemView.findViewById(R.id.textView);
}
}
// 생성자
SimpleTextAdapter(ArrayList<String> list){
items = list;
}
// 아이템 뷰를 위한 뷰홀더 객체 생성하여 리턴
@Override
public SimpleTextAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.item, parent, false);
SimpleTextAdapter.ViewHolder vh = new SimpleTextAdapter.ViewHolder(view);
return vh;
}
// position에 해당하는 데이터를 뷰홀더의 아이템 뷰에 표시
@Override
public void onBindViewHolder(SimpleTextAdapter.ViewHolder holder, int position) {
String text = items.get(position);
holder.textView.setText(text);
}
// 전체 데이터 개수 리턴
@Override
public int getItemCount() {
return items.size();
}
}
RecyclerView.Adapter를 상속받는 SimpleTextAdapter Adapter를 만들었다.
Adapter 내에서 뷰홀더를 위한 클래스를 구현했다.
그리고 뷰홀더에서는 아이템에 표시될 텍스트뷰에 대한 참조를 갖도록 만들었다.
이렇게 작성한 뷰홀더는 Adapter의 onCreateViewHolder()와 onBindViewHolder()메서드를 통해 각각 생성 및 바인딩되어 화면에 표시된다.
4. RecyclerView에 Adapter와 Layout Manager 지정하기
package com.example.recyclerview;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ArrayList<String> list = new ArrayList<>();
for(int i = 0; i < 100; i++){
list.add(String.format("Text %d", i));
}
RecyclerView recyclerView = findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
SimpleTextAdapter adapter = new SimpleTextAdapter(list);
recyclerView.setAdapter(adapter);
}
}
레이아웃 매니저를 지정할 때 LinearLayoutManager 객체를 사용했다. 이는 화면을 수직 방향으로 나열되도록 설계하였기 때문이고, LinearLayoutManager 는 orientation 기본 값이 “VERTICAL”이므로 객체를 생성하면 수직 방향으로 아이템을 표시하게 된다.
만약 수평 방향으로 배치하고 싶다면 아래 코드처럼 객체 생성 시 아이템 배치 방향을 바꿔주면 된다.
recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)) ;
5. 실행화면
실행 시 for문으로 넣어준 Text i가 각 아이템으로 추가된 것을 확인할 수 있다.
📌 참고
[1] https://recipes4dev.tistory.com/154 (이론 내용)
[2] https://velog.io/@haero_kim/Android-ViewHolder-%ED%8C%A8%ED%84%B4%EC%9D%84-%EC%93%B0%EB%8A%94-%EC%9D%B4%EC%9C%A0 (이론 내용)
[3] https://dev-imaec.tistory.com/27 (코드 참고)