Android

[Android] RecyclerView (1) - 개념 및 구조

도우 2024. 2. 14. 16:13
반응형

 

1. RecyclerView 란?

RecyclerView란 안드로이드 공식 문서에서 데이터에 해당하는 뷰가 표함된 ViewGroup이라고 정의하고 있다.

즉, RecyclerView는 데이터를 표시하기 위해 어댑터, 뷰홀더, 레이아웃 매니저 등의 구성 요소를 사용하여 데이터를 관리하고, 이를 효율적으로 뷰로 변환하여 사용자에게 표시하는 과정 전체를 일컫는다.

ListView와의 차이점은 "뷰 재사용" 기법을 사용한다는 것인데, 화면에 보이지 않는 항목의 뷰를 새로운 데이터 항목에 재사용함으로써 성능을 향상시킨다. 이를 위해 뷰홀더(ViewHolder) 패턴을 사용한다.

출처 : https://velog.io/@godmin66/RecyclerView%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%B4-%EB%B3%B4%EC%9E%90

 

2. RecyclerView의 구조

RecyclerView의 구조는 크게 3가지로 분류할 수 있다.

 

출처 : https://velog.io/@godmin66/RecyclerView%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%B4-%EB%B3%B4%EC%9E%90

 

 

  1. 데이터 (Data Set)
    RecyclerView에 표시되는 항목들의 데이터이다. RecyclerView는 어떠한 종류의 데이터 목록이든 표시할 수 있으며, 일반적으로 모델(Model) 객체의 리스트나 배열 형태로 존재하고, 애플리케이션의 데이터 소스에서 가져온 정보를 포함한다.

  2. 어댑터 (Adapter)
    데이터와 RecycerView 사이의 다리 역할을 하는 컴포넌트이다. 어댑터는 데이터 컬렉션 내의 각 항목을 위한 뷰를 생성하고, 그 뷰에 데이터를 바인딩하는 역할을 한다.

    즉, 데이터 모델을 받아서 사용자 인터페이스에 표시할 수 있는 형태로 변환하는 책임이 있다.

    RecycerView.Adapter를 상속받아 구현하며, 최소한 onCreateViewHolder(), onBindViewHolder(), getItemCount() 메소드를 오버라이드 해야한다.

  3. 레이아웃 매니저 (Layout Manager)
    RecyclerView 내의 항목들이 어떻게 배치될지 결정하는 컴포넌트이다. LinearLayoutmanager, GridLayoutManager, StaggeredGridLayoutManager 등이 포함된다.

 

즉, 데이터 목록을 아이템 단위의 뷰로 구성하여 화면에 표시하기 위해 "어댑터(Adapter)"를 사용하며,
수직(Vertical), 수평(Horizontal), 격자(Grid) 등의 레이아웃을 관리하기 위해 "레이아웃 매니저"가 존재한다.
마지막으로 레이아웃 매니저가 제공하는 형태로 어댑터를 통해 만들어진 각 아이템 뷰는 "뷰홀더(ViewHolder)" 객체에 저장되어 화면에 표시되고, 생성 또는 재활용 된다.

 

※ 바인딩 : 데이터를 뷰에 연결하는 프로세스
이 과정에서 애플리케이션의 데이터 모델에서 가져온 데이터가 각 RecyclerView 항목의 뷰 요소에 설정된다.
바인딩을 통해, 데이터는 사용자가 인터페이스를 통해 볼 수 있는 시각적 요소로 변환된다.

3. RecyclerView에서 Adapter의 역할

※ ViewHolder는 Adapter의 내부 클래스이며 아래에 후술한다.

  1. 뷰 관리 / onCreateViewHolder()
    RecycerView에서 새로운 뷰 홀더를 필요로 할 때 호출된다. 즉, 각 항목의 레이아웃을 확장(inflate)하고, 이를 감싸는 ViewHolder 객체를 생성한다. ViewHolder의 주된 역할은 항목 뷰 내의 모든 서브 뷰에 대한 참조를 제공하여, 데이터 바인딩 시 재활용할 수 있게 하는 것이다. 이 메서드는 ViewHolder와 그에 연결된 View를 생성하고 초기화하지만 뷰의 콘텐츠는 채우지 않는다. 아직 ViewHolder가 특정 데이터에 바인딩된 상태가 아니기 때문이다.

    => 이 메소드는 RecyclerView의 항목(item)이 처음으로 화면에 표시될 때 호출됩니다. 목적은 ViewHolder 객체를 생성하고 초기화하는 것으로, ViewHolder는 항목 뷰(item view)에 대한 참조를 보유하고 있어서 데이터 바인딩(data binding) 시 재사용될 수 있습니다.

  2. 데이터 바인딩 / onBindViewHolder() 
    RecyclerView는 ViewHolder를 데이터와 연결할 때 이 메서드를 호출한다. 또한 ViewHolder가 재사용될 때 호출되며, 특정 위치의 데이터를 뷰 홀더의 레이아웃 요소에 바운딩한다. position 매개변수를 통해 어떤 데이터를 현재 뷰 항목에 할당할지 결정하며, 이 데이터를 ViewHolder의 뷰에 설정한다.

  3. 데이터 변경 관리 / ( notifyDataSetChanged(), notifyItemInserted(), notifyItemRemoved() )
    데이터 세트가 변경될 때 (ex : 항목 추가, 삭제, 데이터 갱신) 어댑테는 이러한 변경사항을 RecyclerView에 알려 뷰를 적절히 갱신한다. 이를 통해 변경된 데이터에 맞춰서 최신 상태를 반영하도록 한다.

  4.  데이터 세트 크기 반환 / getItemCount()
    RecyclerView에 표시할 데이터 세트의 크기(항목 수)를 반환한다. 이 메소드는 RecyclerView가 스크롤 가능한 범위를 결정하고 필요한 만큼 뷰 홀더를 생성 및 재사용하기 위해 사용된다.


4. Adapter와 ViewHolder

공식문서에 ViewHolder는 목록에 있는 개별 항목의 레이아웃을 포함하는 View의 래퍼라고 정의하고 있다.

이는 레이아웃 뷰의 참조를 보관하는 컨테이너 역할을 한다고 볼 수 있으며, 각각의 ViewHolder 인스턴스는 특정 항목의 뷰 구조에 대한 참조를 보관하며 이를 통해 뷰에 쉽게 접근할 수 있다.

 

 

RecyclerView에서 아이템 항목 각각을 나타내는 것이 ViewHolder 이라고 생각하면 편하다.
ViewHolder는 화면에 표시할 각 아이템 뷰를 저장하는 역할을 하며, 데이터와 리스트 항목 뷰를 바인딩한다.

예를 들자면, 데이터 개수가 약 100개라고 가정 했을 때, 화면에 보이는 20개와 보이지 않는 10개 총 30개의 뷰홀더가 재사용되면서 100개의 리스트를 모두 보여주는 것이다. 

즉, 화면에 보이는 항목에 대해서만 ViewHolder를 생성하고, 스크롤을 할 때 화면 밖으로 사라진 항목의 ViewHolder를 재사용하여 새로운 데이터를 보여주는 방식으로 작동한다.
( ex : 100개의 데이터 => 실제로 보이는 화면의 20개, 보이지 않는 10개 )

RecyclerView 목록의 각 개별 요소는 뷰 홀더 객체로 정의된다. 뷰 홀더가 생성되었을 때는 뷰 홀더에 연결된 데이터가 없다. 뷰 홀더가 생성된 이후 RecyclerView가 뷰 홀더를 뷰의 데이터에 바인딩한다. RecyclerView.ViewHolder를 확장하여 뷰 홀더를 정의할 수 있다.

    public static class ViewHolder extends RecyclerView.ViewHolder { 
        private final TextView textView;

        public ViewHolder(View view) {
            super(view);

            textView = view.findViewById(R.id.textView); // 변수 할당
        }

        public TextView getTextView() {
            return textView;
        }
    }

 

즉, ViewHolder는 RecyclerView 행 레이아웃의 모든 뷰를 가져와서 변수에 할당하는 것이라고 볼 수 있다.
=> RecyclerView의 각 항목에 대한 뷰 참조를 보관한다는 말과 동일 / onCreate() 와 유사함

이렇게 하면 데이터와 뷰를 바인딩할 때마다 findViewById를 호출하여 뷰를 찾는 비효율성을 줄일 수 있다. findViewById는 CPU 리소스를 상당히 많이 사용하는 연산이기에 이러한 호출을 최소화하고 성능을 개선할 수 있다.

RecyclerView에서는 여러 종류의 뷰홀더를 사용할 수 있다. getItemViewType(int position) 메소드를 오버라이드하여 구현할 수 있으며, 이 메소드는 각 항목의 위치에 따라 다른 뷰 유형을 반환할 수 있다. 이를 통해서 서로 다른 레이아웃을 가진 항목(ex : 헤더, 아이템, 푸터)에 맞게 여러 뷰홀더를 정의하고 사용할 수 있다.

RecyclerView Adapter의 역할에서 뷰 관리와 데이터 바인딩이 있다고 서술했다. 일반적으로 ViewHolder는 RecyclerView.Adapter의 내부 클래스로 구현된다. 따라서 Adapter 내의 내부 클래스에 ViewHolder가 존재 하는 것이므로 adapter 자체가 뷰를 관리하며, ViewHolder라는 개념을 adapter 하위개념 또는 구성요소로 인식할 수 있다.

=> 즉, RecyclerView의 어댑터(Adapter)는 뷰 홀더(ViewHolder)를 사용하여 뷰(View)의 생성과 관리를 담당한다.

 

따라서 정리하자면

어댑터의 역할

- 데이터와 뷰의 연결/관리  : 데이터 세트와 RecyclerView 내의 각 뷰 사이의 연결을 관리.
=> 데이터 세트의 각 항목을 뷰에 매핑하여 인터페이스에 표시

- 뷰 홀더 생성  : ViewHolder 객체 생성 
=> 필요에 따라 뷰 홀더를 생성 / onCreateViewHolder()

- 데이터 바인딩 : ViewHolder에 보관된 뷰에 데이터를 설정
=> 뷰 홀더에 데이터를 바인딩 / onBindViewHolder()

뷰 홀더의 역할

- 뷰의 재사용
- 뷰 참조의 보관

 

RecyclerView를 작성하기 위한 워크플로우는 다음과 같다.

  1. Activity or Fragment에 RecyclerView 작성
  2. 아이템의 목록을 나타낼 행 레이아웃 작성
  3. 어떤 데이터를 출력할 것인지 데이터 모델 작성
  4. 리사이클러뷰 어댑터 작성
  5. 리사이클러뷰에 어댑터 연결 및 레이아웃 매니저 설정

 

다음시간에는 코드를 통해 RecyclerView를 구현해보도록 하자.

 

 

반응형