RecyclerView란 'A flexible view for providing a limited window into a large data set' 으로
한 화면에 표시할 수 없는 많은 데이터를 스크롤 가능한 리스트로 표시해주는 위젯이다.
리사이클러뷰는 뷰홀더 패턴을 사용하여 화면 밖으로 스크롤된 아이템 뷰를 메모리에 유지하고 재사용할 수 있는데, 이를 통해 불필요한 뷰 객체 생성과 파괴를 줄여 성능과 메모리 사용량을 개선하기 때문에 많은 데이터도 리스트 처럼 담을 수 있는 것이다.
목록을 구성하는데 사용되는 뷰로는 ListView 도 있지만 성능상 최근엔 RecyclerView를 더 선호하는 편이다. 주요클래스로 특징을 살펴보자!
Adapter : 기존의 ListView에서 사용하는 Adapter와 같은 개념으로 데이터와 아이템에 대한 View 생성.
ViewHolder : 재활용 View에 대한 모든 서브 뷰를 보유.
LayoutManager : 아이템 항목을 어떻게 배치하는가를 결정.
ItemDecoration : 아이템에 대한 데코레이션(경계선, 여백, 그림자 등) 을 제공하는 클래스.
ItemAnimation : 아이템 항목이 추가, 삭제되거나 정렬될 때 애니메이션 처리.
Adapter : 데이터를 가져와 레이아웃에 적절하게 바인딩하는 역할의 클래스.
ViewHolder : 아이템의 뷰(View)를 저장하고 관리하는 도구
LayoutManger

item_recycler_view.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:paddingVertical="10dp"
android:paddingHorizontal="10dp"
android:background="@color/purple"
xmlns:app="http://schemas.android.com/apk/res-auto">
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="이름"
android:textStyle="bold"
android:layout_marginLeft="20dp"
android:textSize="24sp"
android:textColor="@color/black"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="@+id/tv_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="나이"
android:layout_marginLeft="20dp"
android:textSize="18sp"
android:textColor="@color/black"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_name" />
</androidx.constraintlayout.widget.ConstraintLayout>
res > values > color.xml 에서 배경에 넣을 색 값을 추가. (전 연보라색 했습니다!!)
<color name="purple">#E8CCFF</color>
BoardItem.kt
data class BoardItem(val name: String, val age: String)
리스트의 각 아이템의 내용이 담길 데이터 클래스를 만듭니다.
class BoardAdapter(val itemList: ArrayList<BoardItem>) :
RecyclerView.Adapter<BoardAdapter.BoardViewHolder>() {
// viewGroup : 다른 뷰들을 포함하는 컨테이너 역할의 클래스. (linearLayout, RelativeLayout, FrameLayout..)
// context : 액티비티, 서비스 컴포넌트가 이를 상속받음 -> 실행앱 정보, 리소스 접근 ..
// LayoutInflater : 안드로이드에서 XML 레이아웃 파일을 실제 뷰 객체로 인플레이션하는 역할의 클래스
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BoardViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_recycler_ex, parent, false)
//R.layout.item_recycler_ex <-를 parent.context에서 인플레이션하여 뷰 객체(view) 생성.
return BoardViewHolder(view)
}
override fun onBindViewHolder(holder: BoardViewHolder, position: Int) {
holder.tv_age.text = itemList[position].age
holder.tv_name.text = itemList[position].name
// ViewHolder의 tv_age라는 TextView의 텍스트를 itemList에서 해당 position에 있는 아이템의 나이(age)로 설정합니다.
//onCreateViewHolder 는 리사이클러 뷰가 생성될 때만 호출되지만, onBindViewHolder 는 스크롤 할때마다 호출이 된다.
}
override fun getItemCount(): Int {
return itemList.count()
}
// RecyclerView에 표시할 아이템의 개수를 반환 = 위 클래스에서 매개변수로 받은 itemList 의 길이
inner class BoardViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val tv_age = itemView.findViewById<TextView>(R.id.tv_age)
val tv_name = itemView.findViewById<TextView>(R.id.tv_name)
}
}
onCreateViewHolder, BoardViewHolder, getItemCount 클래스를 오버라이딩 합니다.
(RecyclerView.Adapter<BoardAdapter.BoardViewHolder>() 의 기능을 상속받는 "BoardAdapter" 를 사용하기 위함)
onCreateViewHolder -> 아이템 레이아웃과 결합
onBindBiewHolder -> view 에 내용입력
getItemCount -> 리스트내 아이템 갯수
BoardViewHolder -> 레이아웃 내 View 연결
activity_main.xml
![]()
<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">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/profile"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:orientation="vertical"
tools:listitem="@layout/item_recycler_ex"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
<!-- listitem : 리사이클러뷰에 리스트 아이템으로 item_recycler_ex(낱개) 넣음-->
</androidx.constraintlayout.widget.ConstraintLayout>
가로방향으로 배치하려면 vertical을 horizontal로 바꾸면 된다.
만약 격자무늬로 배치하고 싶으면 LinearLayoutManager 대신 GridLayoutManager를 사용.
MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var binding : ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
// <> : 실제 리스트에 저장될 데이터의 타입을 의미
val rv_board = binding.profile
val itemList = ArrayList<BoardItem>()
// !! : Kotlin에서 Nullable 타입을 Non-Nullable로 강제로 변환하는 연산자. null 값이 아님을 확신.
itemList.add(BoardItem("예진", "17세"))
itemList.add(BoardItem("지민", "17세"))
itemList.add(BoardItem("예지", "16세"))
itemList.add(BoardItem("현서", "17세"))
itemList.add(BoardItem( "소현", "17세"))
itemList.add(BoardItem( "기준", "29세"))
itemList.add(BoardItem( "수현", "27세"))
itemList.add(BoardItem( "상윤", "32세"))
// ArrayList(itemList) 를 사용해 Adapter를 만든 후, notifyDataSetChange()로 어댑터와 리사이클러뷰를 갱신 시킨다. (다시 그려서 화면에 보여준다)
val boardAdapter = BoardAdapter(itemList)
boardAdapter.notifyDataSetChanged()
rv_board.adapter = boardAdapter
rv_board.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
// 레이아웃 매니저 설정 = 리사이클러뷰 안에 아이템들을 어떤 방식으로 배치할지를 결정
// VERTICAL: 세로배치, HORIZONTAL: 가로배치 / false: 스크롤 역순x
}
}
참고자료 : https://uknowblog.tistory.com/29
정리해도 어려운 것 같습니다.. 나중에 binding 활용해서 다시 한 번 도전해볼게요. 완성~!
![]()