개요
제가 앱을 개발할 때 리사이클러뷰를 상당히 많이 사용합니다. 앱에서 스크롤하며 보는 화면은 거이 리사이클러뷰를 사용했다고 볼 수 있을정도로 많이 사용하며, 개발하기도 생각보다 까다로운 위젯이자 라이브러리 입니다. 그렇기 때문에 조금만 연습하면 금방 익숙해 질 수 있는 기능입니다. 많은 분들이 이 리사이클러뷰에 대해서 매우 익숙할거라고 생각합니다. 이러한 리사이클러뷰를 이론적으로 알아보려고합니다.
리사이클러뷰의 사용
화면에 어떤 데이터를 리스트형식으로 보여줘야한다면 리사이클러뷰를 사용하면 됩니다.
리사이클러뷰는 많은양의 데이터를 효과적으로 디스플해줍니다. 리사이클러뷰 라이브러리를 사용하면 이 라이브러리가 알아서 우리가 필요로할 때 다이나믹하게 항목을 생성해주기때문에, 리사이클러뷰를 사용하면 우리는 리스트의 항목을 디자인하여 어떻게 보여줄 것인가만을 생각하면 됩니다.
리사이클러뷰는 이름에서도 유추 해 볼 수 있듯이 무엇인가를 재활용하는기능이 주요기능 중 하나입니다. 예를들면 우리가 리스트를 위에서 아래로 스크롤 가장 아래에 있는 항목은 화면에서 사라지고, 가장위에서는 새로운 항목이 내려오게됩니다. 이 때 리사이클러뷰는 이 사라지는 항목과 새로 내려오는 항목을 생성을 하거나 제거하지 않고, 가장아래 있는 항목을 재활용하여 위로 보내는 기능을 제공해줍니다. 이러한 기능은 우리가 스크롤할때 굉장히 빠른게 동작 할 수 있는 성능을 만들어줍니다.
주요 클래스
리사이클러뷰는 다른 여러 클래스들과 함께 동작을 하며 만들 수 있는데 이 클래스들에서 알아보도록하겠습니다.
- 리사이클러뷰는 뷰그룹입니다. 뷰그룹은 우리가 일반적으로 사용하는 레이아웃도 뷰그룹이라고 할 수 있는데요, 뷰그룹안에 여러가지 위젯들을 배치 할 수 있는 점이 주요 특징입니다. 이에따라 리사이클러뷰에도 여러가지 위젯을 배치하여 레이아웃단위로 UI 요소를 추가 할 수 있습니다.
- 리스트 화면에는 각 각의 항목이 있습니다. 이 항목들의 디자인은 어디서 구현할까요? 바로 ViewHolde라는 클래스를 사용하여 만들 수 있습니다. 리사이클러뷰는 ViewHolder클래스를 상속받은 레이아웃만들 생성해 낼 수 있습니다. 리사이클러뷰에서 ViewHolder를 생성 할 때는 데이터가 연동되지 않은 빈 ViewHolder를 생성해냅니다. 생성되고 난 후 리사이클러뷰 라이브러리에서 데이터를 연동해야하는 시점에 함수를 호출해주는데 이 때 연동하면 됩니다.
- 라사이클러뷰에서 뷰홀더를 생성하고 데이터를 연결해줘야합니다. 이 기능은 RecyclerView.Adapter 클래스를 통해 구현 할 수 있습니다. 그러기 떄문에 이 RecyclerView.Adapter 클래스도 필수적으로 구현해서 RecyvlerView와 연결해줘야합니다.
- 마지막으로 LayoutManager라는 클래스가 있습니다. 이 클래스는 리사이클러뷰에 배치되는 항목들을 설정해 줄 수 있습니다, 예를들면 일반적인 하나의 항목을 새로로 배치할 수 있고, 가로로도 배치 할 수 있습니다. 한 줄에 2개의 항목 또는 3개의 항목이 나오게도 할 수 있습니다. 이러한 설정은 LayoutManager을 통해서 해줘야합니다.
보통 초반 리사이클러뷰 개발이 익숙하지 않을 때 LayoutManager를 설정을 안해줘서 다 구현하고도 리스트가 안나오는 현상을 경험하게 되므로 LayoutManager를 빼먹지 않도록 주의해야합니다.
리사이클러뷰를 실행하기위한 단계
리사이클러뷰를 사용하려할 때 알아야 할 사항 몇 가지가 있습니다.
- 먼저 어떤형식으로 보여줄지 결정을 해야합니다. 예를들면 새로로 하나의 항목씩 보여 줄 수도 있고 한줄에 2개의 항목을 보여 줄 수도 있습니다. 가로로 보여주는 방법도 있습니다.
- 그다음은 항목을 디자인하는 일입니다. 그리고 이 항목을 구현할때는 ViewHolder란 클래스를 상속해야합니다. 이 뷰홀더를 통해 우리는 항목의 기능들을 구현해야합니다. 이 ViewHolder은 View로 감싸져있고, 리사이클러뷰는 이 ViewHolder를 통해서만 항목을 관리 할 수 있기때문에 반드시 ViewHolder를 사용해야합니다.
- 마지막으로 Adapter 를 작성해야합니다. 이 Adapter 클래스는 데이터와 ViewHolder를 연관시켜주는 일을 합니다.
추가적으로 향상된 커스텀 옵션기능을 사용하여 리사이클러뷰에 적용 할 수 있습니다.
레이아웃 메니저 적용하기
리사이클러뷰에서 항목들을 정렬하려면 LayoutManager를 사용해야합니다. 리사이클러뷰 라이브러리에서는 3가지의 LayoutManager를 제공해주고 있습니다. 각 각 어떤 기능을 제공해주는지 알아보도록 하겠습니다.
- LinearLayoutManager는 1차원으로 배열 할 수 있습니다.
- GridLayoutManager은 2차원으로 배열 할 수 있습니다.
- 만약 세로 격자로 배열 할 경우, 각 로우의 가로와 세로의 크기가 같습니다. 하지만 로우별로 높이를 다르게 할 수 있습니다.
- 만약 가로 격자 배열 할 경우, 각 컬럼은 똑같은 가로, 세로 크기를 같습니다. 하지만 컬럼별로 넓이를 다르게 할 수 있습니다.
- StaggeredGridLayoutManager는 GridLayoutManager와 비슷합니다. 하지만 각 항목의 높이와 넓이가 같지 않습니다.
우리는 각 항목의 레이이웃이 다르게 구성이 필요 할 경우도 있습니다. 이때는 뷰홀더를 설계할 때 구현해야합니다. 이부분은 나중에 알아보도록 하겠습니다.
아답터(Adapter)와 뷰홀더(ViewHolder) 구현하기
일단 레이아웃을 결정했다면 Adapter과 ViewHolder을 구현해야합니다. 이 두 클래스들은 어떻게 데이터들을 보여줄 지 처리하는 역할을 합니다. View로 감싸져있는 ViewHolder는 리스트의 각 항목에 레이아웃을 가지고있습니다. Adapter는 ViewHolder를 필요로 할 때 생성하고, 또한 보여질 데이터를 설정합니다. 이 데이터와 뷰를 결합하는 프로세스는 바인딩이라 불립니다.
리사이클러뷰 아답터를 구현 할 때 다음 세가지 함수를 필수로 구현 해야 합니다.
- onCreateViewHolder(): 리사이클러뷰는 화면에 보여지거나 스크롤를 올리고 내리는 상황에서 새로운 항목을 필요로 할 때 ViewHolder를 생성해냅니다. 이 생성하는 시점에는 아직 안에 들어갈 내용에 대해서 알 수 없으므로 생성시점에서만 필요한 기능들을
구현합니다.
- onBindViewHolder() : 리사이클러뷰는 ViewHolder에 데이터를 설정해줘야 할 때 이 함수를 호출합니다. 아마 화면에서 항목이 보여지는 영역에 추가로 위아래 데이터 추가로 로드하고 그 시점에 이 함수가 호출 되지 않을까 생각합니다.
- getItemCount() : 리사이클러뷰는 항목들을 만들기전에 모든항목이 몇 개 인지 우선 알아야 합니다. 그래서 표시해줘야 할 데이터의 크기를 해당 함수를 통해 지정해줘야합니다.
다음은 간단한 예제에 대해서 알아보도록 하겠습니다. 뷰홀더들이 아답터와 함께 데이터를 보여주는 기능입니다. 이 예제는 리사이클러뷰가 간단한 텍스트를 보여주는 예제 입니다.
class CustomAdapter(private val dataSet: Array<String>) :
RecyclerView.Adapter<CustomAdapter.ViewHolder>() {
/** 항목으로 보여줄 뷰홀더를 클래스를 구현했습니다. */
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val textView: TextView
init {
// 텍스트뷰를 설정합니다.
textView = view.findViewById(R.id.textView)
}
}
// 항목을 생성합니다. (레이아웃 메니저로부터 호출 됩니다.)
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
// 항목에 UI로 들어 갈 뷰를 생성합니다.
val view = LayoutInflater.from(viewGroup.context)
.inflate(R.layout.text_row_item, viewGroup, false)
return ViewHolder(view)
}
// 항목의 레이아웃을 재활용하여 안에 있는 내용을 변경 할 때 호출됩니다. (레이아웃 메니저에 의해 호출 됩니다.)
override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
// 항목에 넣어야할 데이터를 데이터 셋으로 부터 가져옵니다.
viewHolder.textView.text = dataSet[position]
}
// 항목의 갯수를 설정합니다. (레이아웃 메니저에 의해 호출됩니다.)
override fun getItemCount() = dataSet.size
}
https://developer.android.com/guide/topics/ui/layout/recyclerview