안드로이드 recyclerView 알아보기. 주요클래스와 내부 동작

이유정·2022년 5월 23일
2

분명 처음에는 Viewholder 공부해보자 하고 시작했는데 listView에 이은 RecyclerView 짚고 넘어가기. 2탄

사실 이 정도면 viewHolder는 이용당한 것이 아닐까. viewHolder 보다는 recyclerView에서 재사용 관련하여 내부 구조를 이해하는 내용이 중심이다.

들어가기 전에

listView와 RecyclerView 모두 기본적으로 리스트 형태로 아이템을 보여주는 뷰그룹 UI이다. 둘의 차이점은 아래와 같다.

listView VS RecyclerView 차이점 :

RecyclerViewListView
ViewHolder필수선택
Item Layout가로 세로 지그제그 모두세로 만
Item Animation처리 클래스 존재OX
Adapter사용자 정의 필요Array/Cursor Adapter 등의 어댑터 존재
DecorationItemDecoration _ 더 많은 구분선 설정Android:divier속성 이용_ 쉽게 가능
Click Detection클릭 처리 기능 구현 필요클릭 관련 인터페이스 존재

뭔가 언뜻 봐서는 listView가 이것저것 제공도 다 하고 더 좋은가 생각이 들지만, RecyclerView가 커스터마이징이 더 편하고 그 외에도 성능이나 그 외 부분에서 더 많은 장점을 가지기에 리싸이클러뷰를 권장한다.

RecyclerView

주요 클래스로는 Adapter, LayoutManager, ViewHolder가 있다.

주요 클래스 간단 정리

  • ViewHolder : 목록의 각 요소는 뷰홀더 객체로 정의된다. 뷰 홀더 생성 시에는 연결 데이터X -> 나중에 recyclerView가 뷰홀더가 가진 뷰에 데이터를 바인딩해주는 방식.
    이 때 ViewHolder는 어댑터가 레이아웃을 inflate할 때 함께 생성, 해당 뷰홀더는 내부 뷰의 참조를 가져오는데, 이렇게 가져온 참조는 레이아웃 재활용 할 때 새 아이템 필요시 뷰에 새 데이터 바인딩하는데 사용됨. 매번 findViewByID할 필요가 없음. 부하down
  • Adapter : RecyclerView가 뷰를 요청 시 _ 어댑터에서 관련 메서드를 호출 하여 뷰에 데이터 바인딩을 해줌.
  • LayoutManager : 목록의 개별 요소를 정렬한다. _ 리싸이클러뷰는 사용자에게 더 이상 표시되지 않는 항목 뷰를 재활용할 시기에 대한 정책을 결정할 책임이 있으며, 아이템 뷰를 측정해고 배치하는 역활을 한다.

Adapter와 ViewHolder 그리고 layoutManager :

  • LayoutManager는 뷰를 배치하면서 "몇번째 포지션의 뷰를 달라!"하며 필요한 뷰를 RecyclerView에게 요청 -> RecyclerView는 필요한 뷰가 재활용 할 수 있는 뷰인지 캐시된 뷰 등을 먼저 탐색하고, 없을 경우 adapter에서 바인딩을 하여 반환해준다.

이때 adapter에서는 ViewHolder 패턴을 활용, onCreateViewHolder, onBindViewHolder, getItemCount, 3개의 추상 메소드를 반드시 구현해주어야 뷰와 아이템의 데이터를 연결, 연결된 뷰를 반환해줄 수 있다.

Adapter 내 각각의 메소드에서 일어나는 일은 다음과 같다.

1.createViewHolder(viewgroup, viewType)
ViewHolder를 새로 만들때 호출. 여기에서 새 view 객체를 생성함과 동시에 이를 만든 viewHolder에 담아 리턴한다.

2.onBindViewHolder(viewholder, position)
parameter로 제공받은 ViewHolder의 value 값을 변경함. -> 데이터 연결해줌.
position은 보통 dataSet에서 몇번째 데이터를 가져올건지에 사용됨.
3. getItemCount()
리싸이클러뷰에서 나타낼 데이터 셋의 크기를 리턴.

재활용에 관해서 어떤 식으로 recyclerView가 일을 하는지, 재사용과 관련하여 공식 문서 recyclerView 페이지 내용을 몇몇 내용을 정리해보았다.

RecyclerView _ (View)

리싸이클러뷰는 재활용을 위해 스크랩되거나 분리된 아이템 뷰를 관리할 책임이 있다. 재활용 가능 상태에 따라 뷰들을 다음과 같이 구분 가능.

  • Recycle(View)는 특정 위치의 동일 데이터 표시된 뷰_ 나중에 다시 사용하기 위해 캐시에 저장됨. 레이아웃 inflate이나 구성 과정 건너뛰기 때문에 성능 향상에 큰 도움을 준다.

  • Scrap(View)는 일시적으로 분리 상태가 된 뷰로서 부모 리싸이클러뷰에 여전히 부착되어 있음. -> 추후 완전히 분리되거나(제거되거나) 혹은 재사용 될 수 있다. _ 리바인딩이 필요하지 않을 경우 바로 재사용되고, 아닐 경우 dirty로 간주되어 어댑터에서 수정됨.

  • Dirty(View)는 어댑터에 의해 리바운드 되어야만 하는 뷰이다.

재사용 RecyclerView.Recycler

레이아웃 메니저는 지정된 포지션 또는 아이템 ID를 가지고 해당 데이터가 나타내는 어댑터의 데이터 셋 대한 뷰들을 가져온다.

만약 뷰의 재사용할 뷰가 dirty로 간주될 경우 어댑터는 다시 바인딩을 해야한다. 혹 뷰가 dirty로 간주되지 않는다면, 추가적 작업 없이(어댑터에서 다시 바인딩 하지 않고) 레이아웃 메니저에 의해 빠르게 재사용이 될 수 있다. (레이아웃을 요청하지 않은? 깨끗한 뷰들은 재측정없이 레이아웃 메니저가 다시 위치를 지정할 수 있다.)

마지막 줄의 깨끗한 뷰들은 ~ 부분이 잘 이해가 가지 않지만, dirty뷰가 아닌 경우 캐시를 이용해서 레이아웃메니저 단에서 재사용할 수 있다는 소리 같다.

내부 동작 다시 정리 :

앞에 내용의 반복 같지만, 햇갈리니 다시 한번 정리해보자.

layoutManager "몇번째 position 뷰 달라!" 요청 ->

RecyclerView "재활용 할게 있나?" 캐시 등 탐색

탐색 결과 있으면 layoutManager에게 줌.
탐색 결과 없으면 adapter가 뷰에 데이터 바인딩 다시해서 넘겨줌.

layoutManager는 반환된 뷰를 가지고 RecyclerView의 아이템 뷰를 배치 및 제어해준다.

RecyclerView는 화면에 보이는 수 만큼의 아이템 뷰를 할당하여 생성하고, 스크롤 등의 이유로 안보이게 된 뷰는 다시 재활용하여 데이터만 새로 셋팅해 보여준다. 이때 adapter는 필요 시 데이터를 바인딩 하기 위해 adapter의 데이터셋에 데이터를 보관한다.

Scrap View일 경우

이때 스크롤에 의해 표시되지 않는 뷰가 scrap view이다.
RecyclerView에는 Scrap Heap Cashing System, scrap뷰를 어댑터로 다시 전달하지 않고 레이아웃 메니저로 직접 반환할 수 있게 한 경량화된 컬랙션이 존재한다.
이를 이용해 다시 데이터를 바인딩하기 위해 뷰를 어댑터로 전달하지 않아도 된다. 해당 뷰는 일시적으로 분리되지만, 동일 레이아웃을 그릴 때 재사용되기 때문이다. >> 데이터가 뷰홀더에 그대로 연결되어 있기에 가능!

바인딩하지 않고 바로 재사용하는 것은 상태값을 가지고 있는, pool을 제외한 다른 캐시에 값이 존재하는 경우에도 가능하다. (scrap 외에도 제거되지 않은 hidden view, ViewCacheExtension 등 여러가지가 존재하는 모양_ 이게 앞서 말한 Recycle(View)인가? )

Dirty View일 경우

= 기존 아이템이 아닌 새로운 아이템을 다시 바인딩해야할 경우 _ 뷰를 재사용하기 위해 recycle pool에서 뷰를 가져와 어댑터에서 새 아이템의 데이터와 뷰를 바인딩함. pool에 캐싱된 뷰는 view와 viewType만 가지고, position이나 flag등 상태 값은 초기화되기 때문.

(+) Recycle pool 관련 주저리
getRecycledView(viewType) : ViewHolder
viewType마다 각각의 뷰홀더 pool을 가지고 있음. 즉 리싸이클러뷰가 scrap이나 다른 뷰 캐쉬를 탐색하면서 찾는 뷰홀더를 찾지 못한다면, 마지막으로 해당 pool에게 viewType에 해당하는 뷰홀더가 있는지 확인하여 뷰홀더를 반환함.

참고사이트
https://developer.android.com/reference/androidx/recyclerview/widget/RecyclerView
https://developer.android.com/reference/androidx/recyclerview/widget/RecyclerView.LayoutManager
https://developer.android.com/reference/androidx/recyclerview/widget/RecyclerView.Recycler
https://medium.com/hongbeomi-dev/%EB%B2%88%EC%97%AD-recyclerview%EC%9D%98-%EB%82%B4%EB%B6%80-%EB%8F%99%EC%9E%91-941a2827fa5a
https://ilovecoffeee.tistory.com/4

profile
개인 공부 블로그

0개의 댓글