How About Recyclerview Mechanism?
우리는 안드로이드 앱을 프로그래밍 할 때, 리사이클러 뷰를 많이, 자주 쓰고 있다. 그렇다면 우리는 이 리사이클러뷰가 내부적으로(안드로이드 시스템 측면에서) 어떤 메커니즘으로 이루어지는 알아볼 필요가 있다.
지금부터 이 리사이클러 뷰는 무엇이고 어떤 식으로 재활용되는지 면밀하게 살펴보자.
리사이클러 뷰는 ViewGroup
이다. 뷰 홀더의 도움으로 데이터를 리스트로 제공하고 스크린에 데이터를 볼 수 있도록 그려준다.
대표적인(a.k.a 구현하기 위해 필요한 기본적인) 컴포넌트들은 3가지다.
Adapter
ViewHolder
LayoutManager
어답터는 RecyclerView.Adapter
의 subtype이다. 이건 리사이클러 뷰에서 유저에게 보여주기 위해 데이터를 세팅하게끔 한다. 한마디로 뷰와 메인 클래스와 연동해서 보여주기 위함이다.
이 리사이클러뷰의 어댑터 클래스 내부에서는 대부분의 많은 일들이 일어난다.
뷰홀더는 우리가 스크린에 보여주고 싶은 UI 구성요소들을 뿌려주기 위해 도와주는 helper class다.
이 클래스(즉, RecyclerView.ViewHolder class의 subclass)에서 각각의 items의 뷰를 모두 연동한다.
리사이클러뷰에서 레이아웃 매니저는 개발자가 스크린에 UI이자 각 뿌려줄 아이템이 뭔지 파악하게끔 도와준다. 이는 linearly 하게 뿌리거나 grid 하게 뿌리도록 할 수 있게 한다. 리사이클러뷰는 기본적으로 layoutmanager의 implementation을 통해 기본적으로 제공한다.
새로운 view를 만들 때, 리사이클러 뷰의 어댑터에게 만든다~
라는 신호를 전해주는 관리 조직과 같다.
이 때까지 기본적으로 리사이클러뷰가 어떤 컴포넌트로 이루어져 있는지 알아봤다면 실질적으로 어떻게 이 뷰가 작동하는지 궁금할 것이다.
우리가 화면에서 스크롤링해야하는 50개의 아이템이 있다고 가정해보자, 그런데 여기서 우리는 5개의 아이템만 한 번에 보여주고 싶다.
item x
는 우리가 위로 스크롤을 올릴 때 로드 될 아이템 중 하나인 아이템이다.
모든 아이템이 각각의 viewholder instance와 viewholder를 가지고 있는 것은 구체적인 아이템 뷰를 캐싱할 때 도움이 될 것이다. 그럼 이때 리사이클러 뷰는 어떻게 적용될까?
먼저 item x에서 item 4까지는 맨 처음 실행했을때 스크린에 보여줘야한다.
그러므로 그들은 visible view mode에서 5개의 아이템이 있는 상태이다. 그 후, item 5은 리스트를 스크롤 업 할 때 다음 새로운 아이템으로 로딩되어야 한다.
우리가 하나의 아이템 위에서 스크롤 할 때, item x와 새로운 item은 움직이고, 보여지는 곳으로 item 5가 올라와야 한다.
그리고 item 6은 waiting view 존 (뷰가 아예 없는 상태는 아니고, 보여지길 기다리는 영역. 위 사진 참고) 에 있을 것이다.
여기서 item x는 스크린 상단으로 이동하고 이를 scrapped view
라고 한다.
scrap view
는 리사이클러 뷰에 있는 특정 뷰로 스마트폰 스크린 영역에서 사용자에게 보였으나 지금은 보이지 않게 되는 영역이다.
그럼 우리가 한 번 스크롤을 통해 다음으로 움직였을 때 item 1은 스크린 밖으로 나가고 item 6는 들어왔다.
여기서 item 1 역시 scrapped view가 됐고 우리는 두 개의 scrapped view를 가지고 있는 상태다. (item x, item 1) 이 아이템들은 a collection of scrapped view에 저장될 것이다.
그리고 지금 우리는 보여지는 영역으로 새로운 view를 로드해야하는 경우, item 7를 생각해보자. 그러면 삭제된 view들이(scrapped view) 사용된다.
이제 item 7을 로드할 때 폐기된 view(scrapped view)의 컬렉션에서 view를 가져온다.
폐기된 뷰에서 로드한 뷰를 dirty view
라고 한다. 이 더티 뷰가 재활용되어 화면 item 7에 표시되어야 하는 대기열의 new item으로 재배치된다.
scrap view collection에서 가져온 view와 re-bound 후 recyclerview 어댑터가 화면에 그리기 전에 나타나는 보기를
dirty view
라고 하기도 한다.
이 flow들이 recyclerview에서 재활용이 일어나는 방법이며, recyclerview 개선의 주된 이유 중 하나이다. 이 프로세스에서 item들은 화면에 new item을 뿌려주는데 재사용 된다.
뷰들을 최적화하는 또 다른 방법은 리사이클러 뷰의 뷰 홀더를 사용하는 것이다.
만약 100개의 아이템이 목록에 있고 5개의 아이템씩 화면에 보여주고 싶은 경우에 어떻게 할 것인가?
여기 각 item들은 textview 와 imageview 1개씩 갖고 있다.
따라서 findViewById
를 사용해 각 item을 연결시키는 것은 비용이 많이 드는 작업이며 이 수를 상상하기만 해도 100개의 항목 그리고 2개 (텍스트 뷰 이미지뷰) 즉, 200개를 매핑해야 한다.
RecyclerView를 사용하는 경우 처음에 6개의 항목만 생성되고 5개가 동시에 로드되어 화면에 보여지고 1개가 로드된다.
이제 목록을 스크롤하면 7개의 viewHolder가 있다. 폐기된 뷰(scrapped view)와 로드된 뷰와 각 보여진 뷰 5개까지 총 7개의 view holder가 있는 상태이다.
그래서 한 번에 최대 findViewByIds는 최대 7개의 viewholder를 갖고 있기 때문에 14개의 findviewbyids를 사용할 수 있다.
View Holder들과 재활용 되는 뷰들 때문에 우리는 Recyclerview의 성능이 향상됐다.
마찬가지로 여러 가지 보기 유형이 있는 경우, View Type 1과 View Type 2를 선택하면 type 1과 type 2 유형의 폐기된 두가지 보기 컬렉션이 생성된다.
또한, 뷰를 재활용 하면서 view type1 뷰는 viewtype1 뷰에만 할당되고 viewtype 2 뷰는 view type 2에 할당 되어 2개의 보기를 할당한다.
이것이 리사이클러뷰를 조금 더 효과적으로 활용하고 적용하는 방법이다.
https://blog.mindorks.com/how-does-recyclerview-work-internally