MultiView Type RecyclerView를 구현할 때, 각 아이템을 분리하여 관리하게 되면 응답 받는 순서에 따라 순서가 뒤 섞이게 됩니다.
응답 받는 순서와 상관 없이 ViewHolder의 순서를 고정 시키는 방법에 대해서 작성 해보았습니다.
ViewType Enum 클래스 선언
enum class DiscoverMultiViewType(val value: Int) {
MARATHON(1000),
RECOMMEND(1001);
}
ViewType 리스트 갱신
데이터 로드가 완료된 ViewType만 리스트에 추가합니다.
데이터 로드에 실패 했거나, 아직 로드 되지 않은 ViewType의 경우 RecyclerView에 표시 되지 않도록 하기 위함입니다.
그리고, 해당 메소드가 ViewHolder의 순서를 정하는 핵심 메소드 입니다.
해당 메소드 내에서 add하는 순서에 따라 화면에 보여지는 ViewHolder의 순서가 정해진다고 보면 됩니다.
private fun initItemViewTypes(): ArrayList<Int> {
return arrayListOf<Int>().apply {
if(marathonList.isNotEmpty()) {
add(DiscoverMultiViewType.MARATHON.value)
}
if(recommendList.isNotEmpty()) {
add(DiscoverMultiViewType.RECOMMEND.value)
}
}
}
ViewType 관련 메소드 선언
RecyclerView의 getItemViewType은 ViewHolder를 생성하기 전에 먼저 호출 됩니다.
RecyclerView.Adapter는 생성 해야될 ViewType을 getItemViewType 메소드를 통해 받아 옵니다.
그리고 그 순서는 첫 번째 아이템부터 시작하기 때문에 initItemViewType에서 add한 순서대로 ViewType이 반환되는 것 입니다.
override fun getItemCount(): Int = viewTypes.size
override fun getItemViewType(position: Int): Int {
return viewTypes.getOrNull(position) ?: DiscoverMultiViewType.RECOMMEND.value
}
ViewHolder 순서 갱신
데이터가 로드 되었을 경우 Adapter에 데이터 셋팅을 해주게 되는데, 이 때 ViewType 리스트를 다시 갱신해주면 됩니다.
아래와 같이 데이터 리스트를 할당 해줄 때 ViewType 리스트에 어떤 ViewHolder를 넣을 지 다시 체크하고, 새로 들어온 데이터의 위치를 알아내어 해당 부분만 notify 해주면 완료 됩니다.
fun setMarathonList(items: ArrayList<MarathonCourse>) {
marathonList.apply {
clear()
addAll(items)
}
refreshViewHolder(DiscoverMultiViewType.MARATHON.value)
}
private fun refreshViewHolder(viewType: Int) {
initViewTypes()
// 현재 ViewType의 첫 인덱스
val startPosition = viewTypes.indexOfFirst { viewType == it }
if (startPosition >= 0) {
notifyItemChanged(startPosition)
}
}
호출하는 쪽에선 데이터 로드가 완료 되면 리스트를 세팅 해주기만 하면 됩니다.
private fun setupRecommendCourseGetStateObserver() {
viewModel.recommendCourseState.observe(viewLifecycleOwner) { state ->
when (state) {
is UiStateV2.Success -> {
dismissLoadingProgressBar()
multiViewAdapter.setRecommendList(ArrayList(state.data))
}
is UiStateV2.Failure -> {
dismissLoadingProgressBar()
/*...*/
}
else -> {}
}
}
실행 결과
첫 번째 데이터 로드에 3초 딜레이를 걸어준 영상 입니다.
늦게 로드 되어도 initViewTypes() 에서 add한 순서에 맞춰 로드 되는 것을 볼 수 있습니다.
'안드로이드 > 이론' 카테고리의 다른 글
[ 안드로이드 ] 앱 내에 개발자 모드 추가하기 3 (0) | 2024.05.16 |
---|---|
[ 안드로이드 ] 액티비티 배경 투명하게 설정 (+ 투명 배경 유지 안되는 이슈 해결) (0) | 2024.03.25 |
[ 안드로이드 ] 앱 내에 개발자 모드 추가하기 2 (0) | 2023.12.29 |
[ 안드로이드 ] 개발자의 실수를 줄여주는 어노테이션 (0) | 2023.12.12 |
[ 안드로이드 ] 앱 내에 개발자 모드 추가하기 (0) | 2023.12.08 |