Apple is Apple
article thumbnail
Published 2023. 8. 10. 15:14
[Android] RecyclerView Android

android jetpack 구성요소 중 하나이다.


대량의 데이터를 동적, 효율적으로 보여주기 위한 뷰 레이아웃이다.

 

기존에 같은방식으로 뷰를 나타내는 ListView가 있다. 그렇다면 왜 ListView가 아니라 RecyclerVIew를 사용할까?

 

ListView? RecyclerView!

ListView에는 몇 가지 단점이 있는데 그중 큰 단점이 하나 있다.

ListView의 특성에 의해 생기는 단점인데, ListView에서 데이터를 불러올 때 모든 데이터를 한 번에 불러오기 때문에 대용량 데이터를 ListView에 보여주려면 속도, 성능(스크롤 시 버벅거림 등) 면에서 문제가 발생한다는 것이다.

 

RecyclerView

RecyclerView에는 뷰의 이름에 있듯이 뷰를 재활용하는 개념이 있다.

ListView와 RecyclerView의 동작 방식 차이

 

위의 그림을 보면 ListView는 모든 요소를 한 번에 불러와 보여주려 하지만 RecyclerView는 일정 개수의 데이터만 불러오고 데이터에 의해 생긴 아이템 뷰가 스크롤 등으로 인해 화면에서 나갈 시 그 나간 뷰를 재활용을 한다. (ViewHolder 패턴 사용)

 

자세한 작동 원리는 이 글 (번역)을 보면 자세히 알 수 있다.  

 

RecyclerView의 주요 구성요소 

1. Adapter 

앱의 데이터뭉치에서 RecyclerView에 표시되는 아이템 뷰에 데이터를 바인딩시키는 곳이다.

어댑터는 RecyclerView의 각 아이템 뷰의 위치를 데이터 소스의 특정 위치에 연결하는 방법을 알고 있다. (ViewHolder를 통해, 밑에서 코드를 통해 알아보자)

 

출처: 개발자를 위한 레시피  https://recipes4dev.tistory.com/154

 

2. LayoutManager

Item들이 RecyclerView 내부에서 배치되는 형태를 관리하는 요소이다. 

미리 정의된 여러 가지 LayoutManager 중 하나(Linear or Grid or StaggeredGrid)를 사용하거나 커스텀 레이아웃 매니저를 구현하여 사용할 수 있다.

출처: 개발자를 위한 레시피  https://recipes4dev.tistory.com/154

 

3. ViewHolder

화면에 그리고 싶은 개별적인 아이템의 UI를 그릴 수 있도록 도와준다. (화면에 표시될 데이터나 아이템들을 저장하는 역할) (RecyclerView의 개념을 적용하기위해선 스크롤 해서 위로 올라간 View를 재활용하기 위해서 이 View를 기억하고 있어야 합니다. ViewHolder가 그역할을 함)

어댑터에 의해 관리되는데, 필요에 따라(좀 더 정확히는, 레이아웃매니저의 아이템 뷰 재활용 정책에 따라) 어댑터에서 생성됩니다.

미리 생성된 뷰홀더 객체가 있는 경우에는 새로이 생성하지 않고 존재하고 있던 뷰홀더를 재활용하는데, 이 때는 단순히 데이터가 뷰홀더의 아이템 뷰에 바인딩된다.

 

출처: 개발자를 위한 레시피  https://recipes4dev.tistory.com/154

 

 

RecyclerView의 주요 구성요소 내부 살펴보기

 

1. Adapter & ViewHolder

 

레이아웃을 결정했으면 Adapter  ViewHolder를 구현해야 한다.

이 두 클래스가 함께 작동하여 데이터 표시 방식을 정의한다.

ViewHolder는 RecyclerView에 있는 개별 항목의 레이아웃(RecyclerView Item) View라고 보면 된다.

 Adapter는 필요에 따라 ViewHolder 객체를 만들고 이러한 뷰에 데이터를 설정하기도 한다. 뷰를 데이터에 연결하는 프로세스를 바인딩이라고 합니다.

 

기본적으로 Adapter는 RecyclerView.Adapter를 상속받아 구현한다.

class Adapter(
	val list: List<Item>
) :RecyclerView.Adapter<Adapter.ViewHolder>() {
    // ViewHolder 클래스
    inner class ViewHolder(private val binding: ItemBinding)
    	:RecyclerView.ViewHolder(binding.root)  {
    	// 리사이클러뷰 각 아이템에 데이터 바인딩 코드 작성
    }

	// 각 아이템의 뷰인 뷰홀더 생성함수
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder =   
        ViewHolder(
                ItemBinding
                    .inflate(
                        LayoutInflater.from(parent.context),
                        parent,
                        false
                    )
            ) 
        
    // 리사이클러뷰가 받는 데이터 셋의 크기     
    override fun getItemCount(): Int = list.size

	// 위치에 따른 데이터 바인딩
    override fun onBindViewHolder(holder: adapter, position: Int) {
       holder.bind(list[position])
    }
}

Adapter는 반드시 세 가지의 메서드를 오버라이드해야 한다.

 

onCreateViewHolder(ViewGroup parent, int viewType) viewType 형태의 아이템 뷰를 생성하기 위한 뷰홀더 객체 생성.

호출시점: RecyclerView가 ViewHolder를 새로 만들어야 할 때
onBindViewHolder(ViewHolder holder, int position) position의 위치에 Viewholder의 Item을 표현

호출 시점: RecyclerView기 ViewHolder를 데이터와 연결할 때 
getItemCount() RecyclerView가 받은 데이터셋의 크기

그리고 Adapter 내에서 ViewHolder 사용을 위해  RecyclerView.ViewHolder를 상속받아서 클래스를 구현한다.

 

이렇게 작성한 ViewHolder는 Adapter의 onCreateViewHolder()와 onBindViewHolder() 메서드를 통해 각각 생성 및 바인딩(데이터 표시)되어 화면에 표시된다.

 

 

2. LayoutManager

 

어댑터와 뷰홀더를 구현하였으면 이제 마무리 작업으로 액티비티나 프래그먼트에서 레이아웃매니저를 RecyclerView에 연결시켜주어야 한다.

class Fragment : Fragment() {
    private var binding: FragmentBinding? = null
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = FragmentBinding.inflate(layoutInflater)
        initRecyclerView()
        return binding?.root
    }

    private fun initRecyclerView() = binding?.let {
        with(it) {
    		// 더미 데이터
            val list = mutableListOf<String>()
            (0..30).forEach { idx ->
                list.add("Item ${idx + 1}")
            }
            
            recyclerView.adapter = Adapter(list)
            recyclerView.layoutManager = LinearLayoutManager(requireContext())
        }
    }
}

 

RecyclerView 객체의 adapter 프로퍼티에 미리 구현한 Adapter와 LayoutManager를 연결시켜 주면 리사이클러뷰 데이터 바인딩 작업이 완료된다.

 

 

 

 

RecyclerView Utility

RecyclerView 최상단 감지 및 이동

if(!recyclerView.canScrollVertically(-1)) {
    // 최상단 감지
}
if(!recyclerView.canScrollVertically(1)) {
    // 최하단 감지
}

 

RecyclerView.scrollToPosition(0) - 최상단으로 바로 이동한다.

RecyclerView.smoothScrollToPosition(0) - 최상단으로 서서히 이동한다. (효과가 적용 됨)

 

 

 

 

<-- 필요시 추후 내용 업데이트 -->

 

ref.

 

안드로이드 리사이클러뷰 기본 사용법. (Android RecyclerView)

1. 안드로이드 리사이클러뷰(RecyclerView) 리사이클러뷰(RecyclerView)는, "많은 수의 데이터 집합을, 제한된 영역 내에서 유연하게(flexible) 표시할 수 있도록 만들어주는 위젯"입니다. [안드로이드 개발

recipes4dev.tistory.com

 

[번역] — RecyclerView의 내부 동작

본 글을 Niharika Arora님의 글을 한국어로 번역한 글입니다. 원문 링크👇

medium.com

 

RecyclerView로 동적 목록 만들기  |  Android 개발자  |  Android Developers

컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. RecyclerView로 동적 목록 만들기   Android Jetpack의 구성요소 RecyclerView를 사용하면 대량의 데이터 세트를 효율적

developer.android.com

 

profile

Apple is Apple

@mjjjjjj