필요 기반 지식 Session Android Team 1. ListView와 RecyclerView의 성능적 차이점을 이해하고 있다. 2. RecyclerView를 만드는 방법을 알고 있다. 3. RecyclerView Adapter에서 반드시 override해야 하는 메서드들의 의미를 알고있다.
public final class Recycler { ... final ArrayList mCachedViews = new ArrayList(); int mViewCacheMax = DEFAULT_CACHE_SIZE; static final int DEFAULT_CACHE_SIZE = 2; ... } View Cache Session Android Team 1. mCachedViews에 ViewHolder 캐싱 2. 기본 cache size : 2 3. position 기반의 캐싱 및 탐색 4. Queue와 유사하게 FIFO로 저장됨
RecyclerView.Recycler#getScrapOrHiddenOrCachedHolderForPosition ViewHolder getScrapOrHiddenOrCachedHolderForPosition(int position, boolean dryRun) { final int scrapCount = mAttachedScrap.size(); ... // Search in our first-level recycled view cache. final int cacheSize = mCachedViews.size(); for (int i = 0; i < cacheSize; i++) { final ViewHolder holder = mCachedViews.get(i); // invalid view holders may be in cache if adapter has stable ids as they can be // retrieved via getScrapOrCachedViewForId if (!holder.isInvalid() && holder.getLayoutPosition() == position && !holder.isAttachedToTransitionOverlay()) { if (!dryRun) { mCachedViews.remove(i); } ... return holder; } } return null; }
public final class Recycler { ... RecycledViewPool mRecyclerPool; ... } public static class RecycledViewPool { private static final int DEFAULT_MAX_SCRAP = 5; static class ScrapData { final ArrayList mScrapHeap = new ArrayList<>(); int mMaxScrap = DEFAULT_MAX_SCRAP; long mCreateRunningAverageNs = 0; long mBindRunningAverageNs = 0; } SparseArray mScrap = new SparseArray<>(); ... } RecycledViewPool Session Android Team 1. RecycledViewPool 클래스에서 관리 2. 기본 pool size : 5 3. 별도의 Heap을 가짐 4. ViewType 기반의 캐싱 및 탐색 5. Stack과 유사하게 LIFO로 저장됨
@Nullable ViewHolder tryGetViewHolderForPositionByDeadline(int position, boolean dryRun, long deadlineNs) { ... if (holder == null) { final int offsetPosition = mAdapterHelper.findPositionOffset(position); final int type = mAdapter.getItemViewType(offsetPosition); ... if (holder == null) { // fallback to pool holder = getRecycledViewPool().getRecycledView(type); ... } ... } ... return holder; } RecyclerView.Recycler#tryGetViewHolderForPositionByDeadline 1. view cache 탐색 2. RecycledViewPool 탐색 3. 7번까지 찾지 못했다면 새로운 ViewHolder 생성 (onCreateViewHolder) 4. ViewHolder에 바인딩이 필요하다면 바인딩 실행 (onBindViewHolder)
중간 정리 Session Android Team View Cache는 position을 기반으로 캐싱 및 탐색 Pool은 ViewType을 기반으로 캐싱 및 탐색 View Cache에 들어간 ViewHolder는 데이터에 대한 바인딩을 해제하거나 초기화 하지 않음 Pool에 들어간 ViewHolder는 데이터에 대한 바인딩을 해제 및 초기화 하기 때문에 재바인딩 필요
다루지 못한 RecyclerView 관련 중요한 내용들 Session Android Team 1. 클릭 이벤트는 어디서 처리하는 것이 좋은가? 2. 중첩 스크롤 처리는 어떻게 하는 것이 좋은가? (feat. NestedScrollView) 3. Multi ViewType 부터 ConcatAdapter까지 4. Payload 관련 + NotifyDataSetChanged를 지양하는 이유 + DiffUtil