Recycler View 제대로 이해하기 - RecyclerView lifecycle

2020. 11. 24. 14:39바삭바삭 IT/안드로이드

안드로이드에서 리스트뷰는 많은 데이터들을 일렬로 나열해주는 우리가 자주 볼수있는 화면입니다. 그러나, 매번 스크롤할때마다 새 항목을 만들고 뷰를 생성하는게 비용이 커서 리소스 소비에 그다지 좋지 않다고 할 수 있습니다. 목록의 양이 많으면 그만큼 리소스를 많이 사용하게 되고, 앱의 성능을 저하시키게 되죠. RecyclerView가 나오기 전까지 오랫동안 고민되어 왔던 문제들이였습니다.

 

Google은 2014년 롤리팝 출시와 함께 RecyclerView를 공개했습니다. RecyclerView의 아이디어는 간단했습니다. 사용자가 스크롤할때마다 뷰가 생성되는게 아니라 뷰는 처음 한번만 생성되고 필요할때마다 재사용하는 방법입니다. 뿐만 아니라 전에 ListView에 없던 LayoutManager, ItemDecoration, ItemAnimator 등 과 같은 다른 개선사항들을 제공합니다. 예를들어, 원래는 vertical 스크롤만 가능했다면 이제는 뒤에 설명할 LayoutManager를 통해 horizontal 스크롤도 쉽게 구현할 수 있게 됩니다. 이전의 listView의 무거웠던 역할을 여러 컴포넌트로 분산시켜 recyclerView가 가벼워진 느낌이라고 하면 될것 같습니다.

 

RecyclerView에서는 어떤리스트던 간에 ViewHolder를 필수적으로 갖는것을 강제하고 있습니다. ViewHolder는 뷰를 담는 그릇이라고 말할 수 있는데, android reference에는 다음과 같이 설명이 나와있습니다.

ViewHolder는 각 위치에 대한 뷰와 데이터를 표현한다.RecyclerView.Adapter을 구현할때 ViewHolder를 하위클래스로 만들고 비용이 많이드는 findViewById()결과들을 캐싱하기 위해 필드를 추가해야한다.

그러면 아키텍쳐는 우리가 생성한 ViewHolder를 사용하여 레이아웃의의 복사본 뷰를 만들어 놓고, ViewHolder를 다시 생성하는 대신 캐시에 저장된 뷰들을 사용합니다. 이렇게 재사용하는 이유로 이름이 RecyclerView라고 하는것이죠. 무슨말인지 잘 이해가 안가죠? 일단 그러려니 넘어가봅시다. 


Main Components

RecyclerView의 메인 컴포넌트(클래스)는 크게 3개 입니다.

  • LayoutManager : 리스트 항목을 배치합니다.

  • ItemAnimator : 아이템이 추가, 제거, 정렬될 때의 애니메이션을 처리합니다.

  • Adapter : 리스트의 항목을 구성합니다.

LayoutManager란?

LayoutManager은 RecyclerView가 언제 child view를 재사용할지 알려주는 역할을 합니다. 이 LayoutManager가 없다면 RecyclerView는 어떤 종류의 레이아웃을 화면에 배치해야하는지 알 수 없습니다. LayoutManager에는 3종류가 있습니다.

  1. LinearLayoutManager : 간단한 수직 또는 수평의 레이아웃을 제공합니다.

  2. GridLayoutManger : spans(colums)을 가지는 격자 레이아웃을 제공합니다.

  3. StaggeredLayoutManager : 크기가 제각각인 엇갈린 레이아웃을 제공합니다.

Adapter란?

RecyclerView의 adpter또한 다른 adpater처럼 뷰와 데이터들을 bind하는 역할을 합니다. 일반적인 adapter들은 데이터셋의 크기에 의해 결정되는 getCount()를 갖으며, 새로운 뷰를 생성하고 거기에 데이터를 bind를 반복하는 일을 합니다. ListView나 ViewPager가 사용하는 adapter가 그런 일을 하죠. 반면, RecyclerView는 더 복접한 시스템을 사용해 데이터를 bind하고 뷰를 처리합니다.

 

위에서 말한것처럼 RecyclerView는 ViewHolder를 기본적으로 사용합니다. 그래서 Adapter는 뷰를 생성하지 않고, inflated(xml의 레이아웃이 메모리에 객체화된) 뷰를 갖는 ViewHolder를 생성합니다. 그렇게 ViewHolder가 생성되어 cache에 쌓이면 필요할때 재사용 됩니다.

 

우리가 기억해야할 점은 ViewHolder은 position이 아닌 itemViewType에 의해 생성된다는 것입니다. 그렇게 하므로써 adapter가 재사용할 뷰를 더 쉽게 찾고 쉽게 추가할 수 있게 됩니다.


 

지금까지 기본적인 메인 컴포넌트들을 얘기해 보았다면, 이들이 어떻게 함께 작동하는지 순서를 파악해 볼까요?

Life of a ViewHolder - Birth

LayoutManager가 레이아웃을 찾는동안 RecyclerView에게 뷰객체를 요청합니다(recylerview.getViewForPosition()). RecyclerView는 Cache를 확인해서 찾는 view가 있다면 LayoutManager에게 리턴해줍니다. 

만약 Cache에 없다면 어떻게 할까요? 그럼 RecyclerView는 Adapter에게 이 뷰의 타입이 뭔지 물어봅니다(adapter.getViewType()). 뷰의 타입을 알게되면 Recycled Pool을 확인하여 이 타입의 ViewHolder를 가져옵니다. Recycled Pool은 여러 RecycledView들 끼리공유할 수 있는 Pool입니다. 만약 Recycled Pool에 ViewHolder가 없다면 RecyclerView는 adapter에게 뷰홀더를 새로 만들것을 요청합니다(createViewHolder)

이미 생성된 경우, Pool에서 ViewHolder가 잘 리턴됩니다. 그러면 이제 adapter에게 bindViewHolder()를 호출해서 특정 position에 이 viewHolder를 bind하라고 요청합니다. adapter는 뷰를 리턴하고, recyclerView는 리턴받은 뷰를 다시 LayoutManager에게 전달해줍니다.

이제 LayoutManager은 RecyclerView에게 이 뷰가 레이아웃에 추가되었다고 말해줍니다. RecyclerView는 adapter에게도 이를 알려줍니다.

Reserves

사용자가 스크롤을 올려버려서 기존의 리스트가 화면에서 안보이게 되었다고 합시다. 그러면 LayoutManager은 view를 제거하고 view는 나중에 재활용 됩니다. 좀더 자세히 살펴볼까요? LayoutManager은 이를 RecyclerView에게 알려주고(removeAndRecyclerView()), RecyclerView는 Adapter에게 알려줍니다(onViewDetachedFromWindow()).

그다음, 이 뷰가 이 position(위치)에 유효한지 확인합니다. 유효한 경우 cache에 유지시키라고 지시합니다. LayoutManager가 이 position에 대해 뷰를 다시 요청할 경우 adapter를 거칠 필요 없이 알려줄수 있게 하기 위해서죠. Cache는 Pool에게 오래된 항목이 삭제되었는지 알려주고, Pool은 Adapter에게 메모리를 절약하기 위해 오래된 항목 내용을 삭제해도 된다고 알려줍니다. 

뷰가 유효하지 않을 때, 예를들어 아이템 항목 하나가 제거되었다고 가정해봅시다. 그런 경우 더이상 유효하지 않기 때문에 이를 Pool에게 보내고 adapter에게 알려줍니다.

Fancy Reserves

LayoutManager가 다시 레이아웃을 계산하는 동안 adapter가 변경된 경우를 살펴봅시다. 그리고 몇개의 뷰는 더이상 사용하지 않게되었습니다. 사용하지 않는 뷰는 각각 숨겨진 adapter list에 추가됩니다. itemAnimator가 끝나고(onAnimationFinished()) 나서 adapter에게 알려주므로(onViewDetachedFromWindow()) recycler가 cache를 업데이트 하고 사용하지 않는 항목을 재활용하도록 합니다.

Death

레이아웃에 뷰가 필요하지 않고 뷰가 transient state(예를 들어 fading out)인 경우, 뷰가 재사용될 수 없으므로 adapter에게 요청합니다(onFailedToRecycle()).adapter는 ViewHolder의 상태를 다시 세팅하고 반환합니다.

Pool은 유형별로 고정된 크기를 가지고, 가득 찬 경우 ViewHolder가 삭제됩니다.


이 글을 쓰는데 참조한 영상과 글 입니다. 아직 이해가 완벽히 안가서 계속 공부하며 글을 다듬어 보겠습니다. :)

www.youtube.com/watch?v=LqBlYJTfLP4

landenlabs.com/android/info/recycler/recycler.html

 

Android Recycler View Lifecycle diagrams and notes

[Go Back] Android Recycler View Lifecycle diagrams and notes Main Components Main RecyclerView components. ViewHolder Life Cycle While Layout Manager is calculating layout, it asks RecyclerView for View objects recyclerView.getViewForPosition(...) Recylcer

landenlabs.com

 

반응형