Android

DiffUtil 사용시 정렬후 스크롤 Top 으로 이동하기

그란. 2021. 12. 29. 19:52

Refresh -> 통신 -> 리스트 변경 -> DiffUtil 동작한 후에 스크롤 맨 위로 올리기 

 

 

 

1. 뷰모델에서 통신을 성공하면 해당 LiveData를 동작

val requestScrollToTop : MutableLiveData<Unit> = SingleLiveData()

 

2. 리스트가 변경됨 

 

3. Activity에서 adapter에 registerAdapterDataObserver 리스너를 연결 

 requestScrollToTop.observe(lifecycleOwner) {
                productAdapter.registerAdapterDataObserver(object :
                    RecyclerView.AdapterDataObserver() {
                    override fun onItemRangeChanged(positionStart: Int, itemCount: Int) {
                        super.onItemRangeChanged(positionStart, itemCount)
                        whenChanged()
                    }

                    override fun onItemRangeChanged(
                        positionStart: Int,
                        itemCount: Int,
                        payload: Any?
                    ) {
                        super.onItemRangeChanged(positionStart, itemCount, payload)
                        whenChanged()
                    }

                    override fun onChanged() {
                        super.onChanged()
                        whenChanged()
                    }

                    override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
                        super.onItemRangeInserted(positionStart, itemCount)
                        whenChanged()
                    }

                    override fun onItemRangeMoved(
                        fromPosition: Int,
                        toPosition: Int,
                        itemCount: Int
                    ) {
                        super.onItemRangeMoved(fromPosition, toPosition, itemCount)
                        whenChanged()
                    }

                    override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
                        super.onItemRangeRemoved(positionStart, itemCount)
                        whenChanged()
                    }

                    private fun whenChanged() {
                        try {
                            productAdapter.unregisterAdapterDataObserver(this)
                            scrollToTop()
                        } catch (e: IllegalStateException) {
                            e.printStackTrace()
                        }
                    }

                    fun scrollToTop() {
                        with(requireViewDataBinding().rvProduct) {
                            post { scrollToPosition(0) }
                        }
                    }
                })
            }

 

-> 포인트는 아이템이 어떻게 변하든 (Removed, Changed, Moved..) 스크롤탑으로 올린 후에 리스너를 바로 해제하는 방법이다.