안드로이드 recyclerview 무한스크롤 기능

한창희·2021년 9월 3일
0

무한스크롤의 이점은 서버에서 받아오는 데이터 개수가 많을 경우 리사이클러뷰에서 한 번에 모두 가져올 필요가 없는 것 같다

일정 개수만큼 데이터를 가져와서 보여주고 스크롤을 밑으로 내리다 끝에 도달한 경우에 추가로 데이터를 가져오기 때문에 시간, 메모리를 절약할 수 있다고 생각한다


mvvm 패턴을 바탕으로 적용을 해봤다

 viewModel.likeChallengeLiveData.observe(viewLifecycleOwner,{
            (likeChallengeBinding!!.recyclerLikeChallenge.adapter as LikeChallengeRecyclerAdapter).updateList(it)
            Log.d("api test check", "updateList called : update recycler list")

         
        })

좋아요 처리를 한 리스트를 가져오는 코드의 일부분이다

뷰모델에서는 서버와의 통신을 호출하고 이 결과 리스트 데이터를 가져와 라이브데이터에 업데이트를 해준다

해당 라이브데이터를 observe하고 있는 fragment 혹은 activity 에서 서버 통신 후 데이터 변경 시 이를 감지하여 adapter를 통해 recyclerview의 데이터를 갱신한다


뷰모델이 서버와의 통신을 하는 시점은 리사이클러뷰에서 스크롤을 내리다 끝에 도달하는 경우일 것이다

이를 위해 리사이클러뷰에 scroll listener를 설정해주었다

 likeChallengeBinding!!.recyclerLikeChallenge.addOnScrollListener(object: RecyclerView.OnScrollListener(){

            override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                super.onScrollStateChanged(recyclerView, newState)

               

                val lastVisibleItemPosition =
                        (recyclerView.layoutManager as LinearLayoutManager?)!!.findLastCompletelyVisibleItemPosition()
                val totalItemViewCount = recyclerView.adapter!!.itemCount-1

                if(newState == 2 && !recyclerView.canScrollVertically(1)
                        && lastVisibleItemPosition == totalItemViewCount){
                    Log.d("api test check", "like recycler 스크롤 마지막 도달로 인한 호출")

                    // 마지막 챌린지 아이디 받아오기
                    var lastChallengeId = (likeChallengeBinding!!.recyclerLikeChallenge.adapter as LikeChallengeRecyclerAdapter)
                            .getLastChallengeId(totalItemViewCount)

                    // 로딩 아이템 뷰 추가
                    (likeChallengeBinding!!.recyclerLikeChallenge.adapter as LikeChallengeRecyclerAdapter).addLoading()

               

                    Log.d("api test check", "lieke recycler 스크롤 마지막 호출 : lastChallengeId : ${lastChallengeId}")
                    viewModel.getAllLikeChallengeList(lastChallengeId, 10, false)



                }
            }


        })

마지막으로 보인 아이템 뷰의 인덱스와 현재 리사이클러뷰에 포함된 데이터 개수-1 을 비교하고 현재 범위에서 더 밑으로 스크롤 할 수 있는지를 검사하여 리사이클러 뷰에서 맨 밑임을 감지했다

추가 데이터를 받아오기 위해서는 마지막으로 보인 데이터의 아이디가 필요했다

마지막 데이터의 아이디를 기준으로 그 다음에 위치한 데이터들을 추가적으로 가져오는 것이다


로딩 화면을 보여주기 위해 리사이클러뷰의 어댑터 내부에
addLoading 이라는 함수를 만들어주었다

addLoading은 데이터들을 보여주는 아이템 뷰홀더와 다른 로딩 화면에 해당하는 뷰홀더를 통해 로딩 아이템 뷰를 생성한다

통신이 끝나면 리스트 변화가 생기므로 위에서 봤던
어댑터의 updateList 함수가 호출되게 된다

updateList 함수 에서는 먼저 addLoading을 통해 마지막 인덱스에 추가한 로딩 아이템 뷰를 제거하고 그 다음 받아온 데이터를 현재 리사이클러 뷰 데이터에 추가로 더해주게 된다


마무리가 되면 자세한 코드를 첨부하도록 하겠다

profile
매 순간 최선을 다하자

0개의 댓글