Android 리사이클러뷰 scrollToPosition과 DiffUtil(ListAdapter와 함께쓰는)

김성준·2023년 4월 9일
0

안드로이드

목록 보기
16/16

이슈

문자 내용을 읽어와서 RecyclerView로 뿌려주는 기능을 개발하면서 RecyclerView와 DiffUtil을 ListAdapter 함께 사용했습니다.

항상 최근 대화를 보여주고 싶어서 RecyclerView의 scrollToPosition을 사용했는데 제대로 작동하지 않았습니다.

스택오버플로우를 찾아보니 Handler.postDelayed()와 함께 사용하면 해결된다는 글들이 보여서 그대로 따라해봤습니다.

직접 해보니 해결은 됐습니다. 근데 왜? delay가 필요할까? 라는 생각이 들어서 직접 알아보았습니다.

RecyclerView와 DiffUtil(with ListAdapter)

Andorid Developer 문서를 찾아보면,

DiffUtil은 두 목록 간의 차이를 계산하고 첫 번째 목록을 두 번째 목록으로 변환하는 업데이트 작업 목록을 출력하는 유틸리티 클래스입니다.

RecyclerView 어댑터의 업데이트를 계산하는 데 사용할 수 있습니다. 백그라운드 스레드에서 DiffUtil 사용을 단순화할 수 있는 ListAdapter 및 AsyncListDiffer을 참조하십시오 .

라고 적혀있습니다.

ListAdapter는 내부적으로 AsyncListDiffer를 사용하여 백그라운드에서 DiffUtil을 활용한 비교작업을 하고 완료되면 메인 스레드(UI 스레드)에 리스트가 바뀌었음을 알려줍니다.

그래서 비교작업이 끝나서 메인스레드가 바뀐 리스트를 알게되기 전에 scrollToPosition을 사용하면 최하단으로 갈 수 없던 것입니다.

해결

ListAdapter의 인자로 scrollToPoition을 호출하는 람다를 넘겨서 onCurrentListChanged 콜백에서 실행하도록 했습니다.

class SmsChatRecyclerAdapter(
	private val scrollToBottom: (Int) -> Unit
    ): ListAdapter<SmsInfo, RecyclerView.ViewHolder>(callback) {
    
   	...
    
    override fun onCurrentListChanged(
        previousList: MutableList<SmsInfo>,
        currentList: MutableList<SmsInfo>
    ) {
        super.onCurrentListChanged(previousList, currentList)
        scrollToBottom(currentList.size - 1)
    }
    
    ...
}

출처

안드로이드 공식 문서 DiffUtil

profile
수신제가치국평천하

0개의 댓글