RecyclerView 는 이미지나 텍스트를 리스트화해서 스크롤하며 볼 수 있게 해주는 컨테이너이다.
기존에 사용하던 ListView 와 비슷하지만, 정확히는 ListView 의 확장판이라고 이야기할 수 있다. ListView 의 확장판이니 당연히, 대부분 RecyclerView 로 대체된 상태이다.
RecyclerView 는 ListView 보다 향상된 성능을 제공하며, Adpater의 ViewHolder를 이용, RecyclerView 내의 View를 재활용하여 사용한다.
ListView 는 사용자가 스크롤 할 때마다 위에 있던 뷰는 삭제되고, 맨 아래의 뷰는 생성되길 반복하여 cost가 매우 높아지게 되는 반면,
RecyclerView에서는 아이템이 100000개를 넘어가더라도 화면에 보이는 정도의 View만 생성하고, 스크롤 할 때마다 삭제하지 않고 가장 아래의 아이템쪽으로 객체를 이동시켜 재사용하게 된다.
데이터 하나하나가 어떻게 들어갈 것인지 틀을 우선 정해주어야 한다. 기존 레이아웃을 작성할 때와 같이 자신의 입맛에 맞게 작성하면 된다.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/layout_selector"
android:id="@+id/item_board">
<TextView
android:id="@+id/item_board_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8sp"
android:layout_marginLeft="8sp"
android:textSize="24sp"
android:textStyle="bold"
android:textColor="@color/colorWhite"
tools:text="TITLE" />
<TextView
android:id="@+id/item_board_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/colorGray"
android:textSize="16sp"
android:layout_marginLeft="8sp"
android:maxLines="1"
android:ellipsize="end"
tools:text="Contents" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8sp"
android:orientation="horizontal">
<TextView
android:id="@+id/item_board_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:textColor="@color/colorGray"
android:textSize="16sp"
tools:text="Time" />
<TextView
android:id="@+id/item_board_writer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:textColor="@color/colorGray"
android:textSize="16sp"
tools:text="Writer" />
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/board_thumup" />
<!-- 중략 -->
</LinearLayout>
</LinearLayout>
완성된 틀은 다음과 같다.
사용할 액티비티에서 RecyclerView 를 추가한다.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".BoardActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
RecyclerView 에 들어갈 데이터들을 정리한다. getter와 setter를 통해 데이터의 입출력이 이루어질 것이다.
package kr.ac.castcommunity.cc.models;
public class Board {
private String title;
private String contents;
private String time;
private String writer;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContents() {
return contents;
}
public void setContents(String contents) {
this.contents = contents;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getWriter() {
return writer;
}
public void setWriter(String writer) {
this.writer = writer;
}
}
가장 핵심적인 부분이다. 우리가 위에서 작성했던 아이템 레이아웃과 데이터를 실제로 연결하는 역할을 수행한다.
package kr.ac.castcommunity.cc.adapters;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
import kr.ac.castcommunity.cc.R;
import kr.ac.castcommunity.cc.models.Board;
public class BoardAdapter extends RecyclerView.Adapter<BoardAdapter.BoardViewHolder> {
// 해당 어댑터의 ViewHolder를 상속받는다.
private List<Board> datas;
public BoardAdapter(List<Board> datas) {
this.datas = datas;
}
@Override
public BoardViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
// ViewHodler 객체를 생성 후 리턴한다.
return new BoardViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_board, parent, false));
}
@Override
public void onBindViewHolder(@NonNull BoardViewHolder holder, int position) {
// ViewHolder 가 재활용 될 때 사용되는 메소드
Board data = datas.get(position);
holder.title.setText(data.getTitle());
holder.contents.setText(data.getContents());
}
@Override
public int getItemCount() {
return datas.size(); // 전체 데이터의 개수 조회
}
// 아이템 뷰를 저장하는 클래스
public class BoardViewHolder extends RecyclerView.ViewHolder {
// ViewHolder 에 필요한 데이터들을 적음.
private TextView title;
private TextView contents;
public BoardViewHolder(@NonNull View itemView) {
super(itemView);
// 아이템 뷰에 필요한 View
title = itemView.findViewById(R.id.item_board_title);
contents = itemView.findViewById(R.id.item_board_content);
}
}
}
액티비티와 리사이클러뷰를 이어주는 역할을 수행하는 어댑터 클래스이다. ViewHolder 가 어떤 역할을 하는지 상세히 살펴보는 것이 좋다.
준비는 모두 끝났으니 실제 RecyclerView 에 연결만 해주면 끝이다.
package kr.ac.castcommunity.cc;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
import kr.ac.castcommunity.cc.adapters.BoardAdapter;
import kr.ac.castcommunity.cc.models.Board;
public class BoardActivity extends AppCompatActivity {
private RecyclerView mPostRecyclerView;
private BoardAdapter mAdpater;
private List<Board> mDatas;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.board);
mPostRecyclerView = findViewById(R.id.recyclerView);
mDatas = new ArrayList<>(); // 샘플 데이터 추가
mDatas.add(new Board("title","contents","time",20,10));
mDatas.add(new Board("title","contents","time",20,10));
mDatas.add(new Board("title","contents","time",20,10));
mDatas.add(new Board("title","contents","time",20,10));
mDatas.add(new Board("title","contents","time",20,10));
// Adapter, LayoutManager 연결
mAdpater = new BoardAdapter(mDatas);
mPostRecyclerView.setAdapter(mAdpater);
mPostRecyclerView.setLayoutManager(new LinearLayoutManager(this));
}
}
새로운 미니 프로젝트는 에브리타임을 모델링하여 만들어질 예정이다. 그 과정에서 안드로이드 게시판을 만들기 위해 ListView 를 알아보다가, 더 개선된 RecyclerView 에 관해 기억을 남기기 위해 해당 글을 포스팅한다.
참고 및 출처