이번 포스팅에서는 Recyclerview를 사용하는 법에 대해 알아보도록 하겠습니다.
Recyclerview의 특징
Recyclerview 는 화면에 리스트 형식의 데이터를 표시하기 위해서 사용하는 모듈입니다. 보통 화면에 리스트뷰를 표시할수 있게 하는 ListView 는 예를들어 데이터가 10개 있을 경우 데이터를 표시하기 위한 ViewHolder가 10개 필요합니다. 그러나 Recyclerview는 ViewHolder 를 6개만 만들고 화면에는 5개를 표시한 후 화면 바깥으로 1번 ViewHolder가 빠져나가면 7번 ViewHolder로 변경해서 재사용합니다. 그래서 자원을 더 아낄 수 있게 되는 것이죠.
또 데이터는 Recyclerview Adapter 를 통해 ViewHolder에 들어가게 되는데 ViewHolder에 데이터 1을 넣어서 표현했을 경우, ViewHolder는 그대로 놔두고 데이터 2를 넣는 식으로 ViewHolder를 재활용해서 사용할 수 있습니다. 그래서 Recyclerview라는 이름이 붙게 된 것이죠.
Recyclerview 구현
라이브러리 추가
우선은 Recyclerview를 사용하기 위한 라이브러리를 추가합니다.
1
2
3
dependencies {
implementation 'androidx.recyclerview:recyclerview:1.1.0'
}
화면 구성
다음은 화면에 Recyclerview 모듈을 추가합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?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" >
<androidx.recyclerview.widget.RecyclerView
android:id= "@+id/recycler_view"
android:layout_width= "match_parent"
android:layout_height= "match_parent"
android:scrollbars= "vertical"
app:layout_constraintBottom_toBottomOf= "parent"
app:layout_constraintEnd_toEndOf= "parent"
app:layout_constraintStart_toStartOf= "parent"
app:layout_constraintTop_toTopOf= "parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
ViewHolder 화면구성
다음으로 ViewHolder의 화면을 구성합니다. ViewHolder는 LinearLayout 에 TextView 2개를 쌓은 단순한 구조로 정의했습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?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"
android:orientation= "vertical" >
<TextView
android:id= "@+id/tv_main"
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:text= "Main TextView"
android:textSize= "24dp"
android:padding= "5dp" />
<TextView
android:id= "@+id/tv_sub"
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:text= "Sub TextView"
android:textSize= "18dp"
android:padding= "5dp" />
</LinearLayout>
Recyclerview 어댑터 작성
다음은 RecyclerView.Adapter 클래스를 상속받는 Recyclerview Adapter
를 작성합니다. 외부에서 전달받을 데이터는 dataSet
이라고 정의했습니다.
그리고 ViewHolder 클래스 를 작성합니다. 여기서는 외부에서 전달받은 데이터를 ViewHolder 화면의 텍스트뷰와 연결하는 작업을 bind
함수로 정의합니다.
onCreateViewHolder
에서 ViewHolder클래스에 list_item
으로 inflate한 객체를 넘겨준 ViewHolder를 작성하여 반환합니다. onBindViewHolder
에서는 ViewHolder 클래스의 bind
함수로 작성된 ViewHolder와 전달받은 개별 데이터를 연결합니다. getItemCount
에서는 전달받은 데이터의 전체길이를 넘겨주어 어댑터가 ViewHolder를 얼마나 만들어야 할지를 결정하게 합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class RecyclerViewAdapter ( private val dataSet : ArrayList < List < String >>): RecyclerView . Adapter < RecyclerViewAdapter . ViewHolder >() {
override fun onCreateViewHolder (
parent : ViewGroup ,
viewType : Int
): ViewHolder {
val view = LayoutInflater . from ( parent . context ). inflate ( R . layout . list_item , parent , false )
return ViewHolder ( view )
}
override fun onBindViewHolder ( holder : ViewHolder , position : Int ) {
holder . bind ( dataSet [ position ])
}
override fun getItemCount (): Int {
return dataSet . size
}
class ViewHolder ( view : View ): RecyclerView . ViewHolder ( view ) {
private val tvMain : TextView = view . tv_main
private val tvSub : TextView = view . tv_sub
fun bind ( data : List < String >) {
tvMain . text = data [ 0 ]
tvSub . text = data [ 1 ]
}
}
}
데이터셋 준비
다음으로 메인액티비티에서 Recyclerview로 넘겨줄 데이터셋을 만듭니다. String
을 두개 포함한 배열을 100개 가지는 리스트의 리스트 형식으로 작성하였습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class MainActivity : AppCompatActivity () {
private val dataSet : ArrayList < List < String >> = arrayListOf ()
override fun onCreate ( savedInstanceState : Bundle ?) {
super . onCreate ( savedInstanceState )
setContentView ( R . layout . activity_main )
addData ()
}
private fun addData () {
for ( i in 0. . 99 ) {
dataSet . add ( listOf ( " $i th main" , " $i th sub" ))
}
}
}
Recyclerview와 Adapter 연결
마지막으로 Recyclerview와 Adapter를 연결해줍니다. Recyclerview 안에서 ViewHolder를 어떻게 정렬할지 결정하는 LayoutManager 프로퍼티를 정의하는데 여기서는 LinearLayoutManager 를 사용하였습니다. 그 외로 GridLayoutManager 나 StaggeredGridLayoutManager 를 사용할 수도 있습니다.
그리고 위에서 만들어 준 RecyclerViewAdapter를 초기화하여 adapter
프로퍼티에 반영해줍니다.
addItemDecoration 속성에 DividerItemDecoration.HORIZONTAL 을 전달하면 각 ViewHolder 사이에 구분선을 표시할 수도 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class MainActivity : AppCompatActivity () {
private val dataSet : ArrayList < List < String >> = arrayListOf ()
override fun onCreate ( savedInstanceState : Bundle ?) {
super . onCreate ( savedInstanceState )
setContentView ( R . layout . activity_main )
addData ()
recycler_view . layoutManager = LinearLayoutManager ( this , LinearLayoutManager . HORIZONTAL , false )
// recycler_view.layoutManager = GridLayoutManager(this, 2)
recycler_view . adapter = RecyclerViewAdapter ( dataSet )
recycler_view . addItemDecoration ( DividerItemDecoration ( this , DividerItemDecoration . HORIZONTAL ))
}
private fun addData () {
for ( i in 0. . 99 ) {
dataSet . add ( listOf ( " $i th main" , " $i th sub" ))
}
}
}
이렇게 해서 Recyclerview를 사용하는 법에 대해 알아보았습니다.
VIDEO