일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 28 | 29 | 30 |
31 |
- 운영체제
- 플로이드워셜
- appcompatacitivity
- AAC
- Kotlin
- Android
- 리사이클러뷰풀
- 내부 단편화
- apk 빌드 과정
- 리사이클러뷰
- 안드로이드
- 물리 메모리
- DiffUtil
- 자이고트
- viewModelScope
- http 역사
- appcompatactivity
- 데코레이터 패턴
- 디자인 패턴
- 절대 주소
- http발전과정
- AsyncListDiffer
- GetX
- NestedScrollView
- recyclerview
- 프로세스
- flutter
- 상태관리
- 뷰홀더
- Dispatchers
- Today
- Total
hong's android
[안드로이드] RecyclerView 본문
리스트뷰와 리사이클러뷰 차이점
- 둘 다 뷰 재활용을 할 수 있지만 리스트 뷰는 뷰 홀더 패턴을 따로 적용해야 합니다. - 리사이클러뷰는 뷰홀더 패턴으로 재활용을 강제합니다.
- 리스트뷰는 애니메이션 지원이 되지 않는다.
- 리사이클러뷰는 를이용해서 수직 스크롤 이외에도 수평 스크롤 지원, 다양한 형태의 리스트들 지원한다.
리사이클러뷰의 뷰홀더 생성과 재사용
1. 스크롤을 내리면 RecyclerView는 스크롤 알림을 Layout Manager에게 보냅니다.
2. Layout Manager는 몇 번째 위치에 새로운 itemview가 배치되어야 하는지를 계산하고 해당 위치를 다시 RecyclerView에게 보냅니다.
3. RecyclerView는 캐시에서 해당위치를 가진 아이템 뷰를 가져오는데 만약 캐시에 해당 아이템 뷰가 없을 때 RecyclecyclerdViewPool에 해당 viewType을 가진 뷰홀더를 요청합니다. (어댑터에게 뷰타입의 종류를 알려달라고 요청합니다.)
4. 그 후 RecyclecyclerdViewPool에 원하는 뷰홀더의 유무에 따라 Adapter에게 다른 요청을 하게 됩니다.
1) 만약 뷰홀더가 있을 경우 해당 뷰홀더를 가지고 Adapter에게 데이터들을 뷰홀더에 Bind만 하도록 요청합니다.
2) 만약 뷰홀더가 없을 경우 Adpater에게 onCreateViewHolder()로 뷰홀더 생성합니다.
뷰홀더는 pool에 바로 재활용되지 않을 수 있습니다.
만약 사용자가 스크롤을 내리면 화면에서 사라지는 아이템 뷰가 생깁니다.
1. 이때 레이아웃 매니저는 리사이클러뷰에게 아이템이 제거되었다고 알려줍니다. 리사이클러뷰는 어댑터에게 또한 onViewDetachedFromWindow()를 호출해서 알려줍니다.
2. 그리고 만약 리사이클러뷰는 해당 아이템이 position에 유효하면 캐시에 저장하도록 요청합니다.
3. 캐시는 오래된 아이템이 존재한다면 pool에 저장하도록 해줍니다.
4. pool은 오래된 캐시가 풀에 저장되었다면 onViewRecylced를 통해 Adapter에게도 알려줍니다.
잠시동안 애니메이션을 위해서 리사이클러뷰의 child로 유지되는 Hidden Views
LayoutManager의 연산과정에 참여되지 않는, 곧 사라질 뷰들은 Hidden View입니다.
Hidden View들은 어떻게 활용되는지 확인해 보겠습니다.
1. 리사이클러뷰는 Layout Manger에게 사라지는 뷰들이 존재한다고 알립니다. (onLayoutChildern())
2. 리사이클러뷰는 사라지는 아이템 뷰들을 다시 뷰그룹에 추가합니다.
3. 리사이클러뷰는 hidden views들의 애니메이션 처리를 ItemAnimator에게 요청합니다.
4. Adapter에게 아이템뷰들이 사라졌다는 것을 알린 후 해당 뷰들을 캐시 또는 Pool에 저장합니다.
뷰홀더가 그대로 제거되는 상황
뷰홀더가 재활용되지 않고 그대로 제거되는 상황은 뷰홀더를 계속 생성하는 상황을 발생시킬 수 있습니다.
첫 번째 경우입니다.
1. ItemView가 애니메이션 중인 상황을 transientState라고 하는데, 해당 상태에 빠진다면 재활용 불가능 하다고 판단합니다. LayoutManager는 해당 상태임을 리사이클러뷰에게 알립니다.
2. 리사이클러뷰는 아이템이 뷰가 유효한지 확인한 후, 유효하지 않다면 pool에게 알립니다.
3. pool은 다시 tansientState(애니메이션 활성화)임을 확인하고, 해당 상태이면 onFailedToRecycle()을 호출합니다.
여기서 만약 onFailedToRecycle()를 true라고 한다면 해당 상황에 "날 믿고 recycle 해!"라는 것을 의미합니다.
반드시 피해야 하는 상황은 아이템을 fade-in 애니메이션을 준 후에, 사용자가 스크롤을 빠르게 해서 애니메이션이 끝나기도 전에 리사이클러뷰의 범위 밖으로 벗어나면 해당 뷰홀더는 재활용 불가능해집니다. 계속해서 새로운 뷰홀더를 생성하는 셈입니다.
⚠️ tansientState는 child에서부터 parent 그리고 root view까지 전파됩니다. 만약 아이템 내부의 어떤 뷰에 애니메이션을 준다면 해당 뷰 뿐만 아니라 뷰홀더가 참조하는 루트 뷰까지 모두 transient state가 됩니다. 예를들어 아이템 내뷰의 텍스트가 수정되고 있는 중이라면 해당 뷰아이템은 transient state 입니다.
두 번째 경우입니다.
1. 리사이클러뷰에서 아이템뷰에 대한 처리를 마쳤고 이를 리사이클러뷰 풀에 저장하도록 합니다. 하지만 pool은 제한된 크기를 가지고 있기 때문에 해당 뷰홀더는 제거됩니다.
그렇기 때문에 pool 사이즈의 크기를 상황에 따라 적절하게 고려해 확장해야 합니다.
RecyclerdViewPool
RecyclerdViewPool의 구현을 확인해 보면 RecyclerView.Recycler의 inner class입니다. 상수로 DEFAULT_MAX_SCRAP가 선언되어 있으며 해당 상수는 뷰타입별 최대 저장할 수 있는 max값이다. RecyclerdViewPool 은 public static으로 선언되어 있으며 여러 recyclerview들이 pool을 공유할 수 있습니다.
public static class RecycledViewPool {
private static final int DEFAULT_MAX_SCRAP = 5;
}
Reference.
2. https://www.youtube.com/watch?app=desktop&v=LqBlYJTfLP4
3. https://velog.io/@dabin/안드로이드-공식문서-파헤치기-RecyclerView의-모든-것-2탄ViewHolder수명주기
'Android > Android' 카테고리의 다른 글
[안드로이드] DiffUtil (0) | 2023.02.21 |
---|---|
[안드로이드] Lru Cache (0) | 2023.02.21 |
[안드로이드] Appcompatactivity (0) | 2023.02.14 |
[안드로이드] apk 빌드 과정 (+ DVM,ART) (0) | 2023.02.11 |
[안드로이드] setcontentview(), Layoutinflater (0) | 2023.01.31 |