https://medium.com/@bansooknam/android-recyclerview-%EC%9A%94%EC%95%BD-aaea4a9c95e7


1. 구성요소

1) 기본 구성요소

1–1)LayoutManager

*리스트, 그리드, 스태그드 그리드 등의 배치를 담당하고
*동시에 스크롤도 담당한다.
*아이템의 focus담당 (리스트를 내릴때 새로운 아이템을 추가해야하는지도 알려준다)

1–2) Adapter

*view, viewHoler생성
*item과 viewHolder를 bind
*RecyclerView에게 changes를 notify
*아이템 클릭등의 interaction 핸들링
*viewTypes 분기
*onFailedToRecyclerView를 통해 Recycler복원

2) 내부 구성요소

2 . Recycle 방법

1) 레이아웃 매니저가 getViewForPosition으로 view를 요청

2) RecyclcerView는 캐시에 getViewForPosition으로 확인. 있으면 LayoutManager에게 반환

3) 캐시에 없으면 adapter에게 type이 뭔지 물어보고 Recycled Pool에 getViewHolderByType으로 요청

4) Pool에 있으면 반환, 없으면 adapter에게 createViewHolder로 아이템 생성.

5) 뷰를 찾으면 adapter에서 bindview를 하고 LayoutManager에게 리턴.

6) LayoutManager는 RecyclerView에게 addView를 수행하고 adapter의 onViewAttachedToWindow가 호출됨.

  • 캐시와 Recycled Pool은 RecyclerView안에 이미 선언되어있음.
  • setItemViewCacheSize함수로 캐시 사이즈 변경 가능.

3. childeren 제어 순서

1) recyclerView가 LayoutManager에게 onLayoutChildren을 하면 배치를 시켜줌.
2) recyclerView에서 지워지거나 추가된 childeren들을 조사해서 알맞는 작업을 진행.
3) recyclerView는 ItemAnimator에게 animateChildren을 호출하여 애니메이션 수행
4) ItemAnimator가 동작을 하고 onAnimationFinished를 호출함.
5) adapter에게 onViewDetachedFromWindow를 호출
5) 상황에 따라서 view를 캐시하거나 재활용을 하게 된다.

4. ItemDecoration

1) getItemOffsets함수를 통해 Item의 영역을 늘릴 수 있다.
2) onDraw함수를 통해서 아이템이 그려지기 전에 먼저 그릴 수 있고
3) onDrawOver함수를 통해서 아이템 위에 덮어서 그릴 수 있다.
4) 주의사항:

  • adapter에 접근하려 하지 말것
  • 그릴때 필요한 정보는 ViewHolder에 넣어둘것
  • viewHolder가 필요할때 recyclerView.getChildViewHolder(view)함수를 통해서 가져올것.

5. 꼭 알아야 할 것

1) 모든 아이템을 notify하는것은 되도록 피해라( notifyItemRangeChanged(0, getItemCount());
->해결 방법. notifyItemChanged(3)

2) onBindViewHolder 메소드 안에 final int position을 사용하지 말라. (final인 position은 보장하지 않는다. 위치가 바뀌거나 지워질때 등)
-> 해결방법. holder.getAdapterPosition을 이용해라.

3) holder.getAdapterPosition()해서 가져온 position값이 RecyclerView.NO_POSITION인지 꼭 확인하도록 해라.
-> 방법. if(holder.getAdapterPosition()!=RecyclerView.NO_POSITION)인지 확인하고 필요한 로직 추가.

4) Item Payload를 활용하라.
-> 방법. adapter.notifyItemChanged(position, LIKE_UPDATE); (좋아요 눌렀을때 처리, 타입을 여러개로 나눠서 필요한 호출을 한다.)
onBindViewHolder(holder, position, List payloads)를 override해서 사용하고
payloads.contains(LIKE_UPDATE) 함수로 좋아요를 눌렀는지 판단해서 로직 처리가 가능하다.

5) onCreateViewHolder에서는 새로운 인스턴스만 반환해라.
-> 전역변수로 holder를 keep했다가 캐시처럼 넘기는 오류는 범하지 말라. 항상 new Holder()를 반환하도록 해라.

6) pool을 메모리 캐시에 놓고 모든 recyclerview에 세팅하지 말라.
:context leak를 유발하게 될것.

7) recyclerView adpater는 single쓰레드 기반이다.
->영향을 주는 list들은 main Thread에서만 변경하도록 해야 정상 동작한다.

출처: android dev summit 2015 영상