본문 바로가기
안드로이드 자바

[Android][Java] 리사이클러뷰 어댑터

by teamnova 2022. 10. 3.

안녕하세요! 오늘은 리사이클러뷰 사용 시 구현되어야하는 '어댑터'에 대해서 알아보고자 합니다. 

 

우선 간단하게 리사이클러뷰에 대해 간략히 알아봅시다.

 

-리사이클러뷰?

 

 뷰가 생성되고 삭제되는 과정에는 큰 비용이 들어갑니다. 리스트뷰(list view)는 갱신될 때 마다 화면 밖 뷰를 삭제하고 보여지는 곳에는 또 새로운 뷰를 생성하여 리스트를 구성했고 이는 성능저하로 연결됐습니다.*리사이클러뷰는 바로 이때 등장합니다. 안드로이드는 뷰의 생성과 삭제를 최소화하고자했고 뷰를 재활용하는 방식으로 문제를 해결하게 되었습니다.  그래서 이름도 리사이클러(recycler view)뷰입니다.

recycle
1.재활용하다 2.다시 이용하다
(출처: 네이버 사전)

 뷰의 재활용이라는 개념을 쉽게 이해하기 위해 아래 그림을 참고해봅시다. 

리스트뷰는 끊임없이 뷰가 생성되고 삭제되는 반면에, 리사이클러뷰는 화면을 스크롤할 때 화면 밖으로 나간 뷰들을 보관했다가 화면에 보여질 때 새롭게 데이터를 바인딩해서 유저에게 보여줍니다.  바로 이 역할을 해주는 것이 어댑터입니다. 

 

-어댑터?

 

그럼 어댑터란 어떤 의미가 있을까요? 

어댑터라는 말을 네이버 사전과 구글에서 검색하게 되면 아래와 같이 정의되어있음을 확인할 수 있습니다.

어댑터 (adapter)
[명사]
1. 기계나 기구 따위를 여러 다른 용도로 사용하기 위해 덧붙이는 기구.(고려대한국어대사전)
2.기계나 기구 따위를 다목적으로 사용하기 위한 보조 기구.또는 그것을 부착하기 위한 보조 기구 (표준국어대사전)
(출처:네이버 사전 출처)

어댑터 (adapter)
 다른 전기나 기계 장치를 서로 연결해서 작동할 수 있도록 만들어 주는 결합 도구.
(출처: 위키백과) 

어댑터를 구글에 검색해보면 이런 이미지가 나옵니다. 

어댑터 검색 시 구글에 나오는 이미지들

사전에서 보이는 '덧붙이는', '부착하는', '서로연결해서 작동해주기 위한'.. 이라는 설명을 읽어보고 아래 이미지를 참고해보면 리사이클러뷰에서 어댑터의 의미 또한 쉽게 유추 가능합니다. 더 나은 이해를 위해 아래 그림을 참고해주세요.

어댑터가 리사이클러뷰와 데이터셋 중간에서 둘을 연결해주고 있음을 알 수 있습니다.

어댑터가 데이터 셋과 리사이클러뷰 사이에서 위치하여 서로 연결해주고 있습니다.  어떤 역할을 하는지 감이 오시나요? 안드로이드 공식 홈페이지에서는 어댑터에 대해 아래와 같이 서술하고있습니다.

An Adapter object acts as a bridge between an AdapterView and the underlying data for that view. The Adapter provides access to the data items. The Adapter is also responsible for making a View for each item in the data set

어댑터는 어댑터뷰 와 해당 뷰의 기본 데이터 사이의 가교 역할을 합니다. 어댑터를 사용하여 데이터 항목에 액세스할 수 있습니다. 또한 어댑터는 데이터셋 각 항목에 대한 뷰를 생성합니다.
출처: https://developer.android.com/reference/android/widget/Adapter

그렇다면 리사이클러뷰 어댑터는 어떻게 중간에서 요소들이 동작할 수 있도록 도와주는걸까요? 그래서 대체 어떻게 재사용된다는걸까요? 어댑터에서 필수적으로 구현해야하는 메소드들을 통해 함께 알아봅시다.

 

-어댑터 내부?

 

어댑터를 구현하기 위해 클래스를 만들고 extend 로 리사이클러뷰 어댑터를 상속 받으면 아래와 같이 메소드들을 implement하라는 안내가 나옵니다.

(1) onCreateViewHolder (2) onBindViewHolder (3) getItemCount 총 세가지 메소드를 확인 할 수 있습니다. 

 

리사이클러뷰 어댑터 구현 화면

하지만 처음 어댑터를 공부하시고 진행하시는 분이라면 해당 메소드들이 직관적이긴하지만 분명 뷰를 재활용한다고 했는데, 도대체 뷰홀더는 뭐지?라고 생각하실 수 있습니다. 

 

 뷰홀더는 말 그대로 뷰를 보관하는 Holder 객체입니다. 본래 리사이클러뷰의 뷰 업데이트 시에는 findViewById()가 호출되는데 findViewById()는 고비용 작업이라 매번 호출 될 시 성능 저하로 이어집니다. 이를 해결하기 위해 나온 것이 뷰홀더라는 개념입니다. 아래 설명으로 빠르게 넘어가기 위해 간단히 서술하자면,  뷰 업데이트 시 불필요한 findViewById()의 호출 피하기위해 findViewById()를 통해 뷰를 불러오지않고 저장 된 객체로 액세스하기 위해 사용합니다. 

 

 리스트뷰에서는 뷰홀더 패턴이 강제되지않으나, 리사이클러뷰에서는 뷰홀더 패턴이 필수입니다. 뷰홀더에 대한 공식 홈의 설명을 읽어봅시다. 

A ViewHolder describes an item view and metadata about its place within the RecyclerView. Adapter implementations should subclass ViewHolder and add fields for caching potentially expensive findViewById results.

뷰홀더는 아이템뷰와 리사이클러뷰 내의 해당 위치(포지션)에 대한 메타데이터를 설명합니다. 어댑터 구현은 잠재적으로 비용이 많이 드는 findViewById 결과를 캐싱하기 위해 Viewholder를 하위 분류하고 필드를 추가해야 합니다.
출처: https://developer.android.com/s/results?hl=ko&q=viewhodler

 

그럼 다시 처음으로 돌아와, 어댑터 내부에서 반드시 구현해야하는 세가지 추상메소드를 간략히 살펴봅시다.

 

메소드 설명 인자 비고
onCreateViewHolder 뷰홀더와 뷰홀더가 파라미터로 받은 를 생성하고 초기화해주는 함수.(파라미터로 받은 뷰를 기억한다.)

위와 같이 생성된 뷰홀더를 리턴한다. 

단 특정 데이터와 바인딩 된 상태가 아니므로 뷰의 콘텐츠는 채우지 않는다.
@param) ViewGroup parent

(어댑터 위치에 바인딩된 후) 새 뷰가 추가될 뷰그룹

@param) int viewType

새 뷰 의 뷰타입
제한적으로 호출.
onBindViewHolder 뷰홀더에 데이터를 바인딩 해주는 함수.  @param) Viewholder holder 

해당 포지션에 있는 아이템의 내용을 나타낼 수 있도록 업데이트 되어야하는 뷰홀더

@param) int position

데이터셋 내 아이템 위치.
무제한 호출.
getItemCount 어댑터 내부에서 가장 먼저 실행되는 함수.

총 데이터셋의 길이를 리턴한다.

리사이클러뷰는 이 메서드를 사용하여, 항목을 추가로 표시할 수 없는 상황을 확인한다.
X 없음  이후 getItemViewType가 호출되어 현재  해당하는 ViewType 판단한다.
	@Override
    public int getItemCount() { return tags.size(); }

맨처음 getItemCount() 메소드가 호출 된 후 onCreateViewHolder()메소드가 호출됩니다. onCreateViewholder()는 처음에 뷰홀더를 생성해내는 메소드입니다.  Layoutinflator를 통해 inflate된 XML레이아웃 파일을 View 클래스의 객체로 받아 뷰홀더에 파라미터로 넘겨주어 뷰홀더 객체를 신규 생성합니다.

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        View view = LayoutInflater.from(parent.getContext())
        				.inflate(R.layout.Rv_item, parent, false); //Rv_item은 xml파일

        return new ViewHolder(LayoutInflater.from(parent.getContext())
                .inflate(R.layout.Rv_item,parent,false));
    }

그러나 어댑터는 계속적으로 뷰홀더를 생성해내는 것이 아니라 제한적으로 생성해내며, 이후에는 onBindViewHolder 메소드를 통해 생성된 뷰홀더를 계속 재활용하여 데이터를 바인딩해주게 됩니다. 

@Override
public void onBindViewHolder(@NonNull ViewHolder holder,
                             @SuppressLint("RecyclerView") int position) {
                             
    //arrayList는 해당 어댑터에서 사용하는 데이터셋이다.

    RvItem item = arrayList.get(position);
    holder.staticRvImg.setImageResource(item.getRvImg());
    holder.staticRvStr.setText(item.getRvStr());
    
    }

 

 로그를 찍어보았을 때 처음에는 이렇게 onCreateViewHolder가 찍히는 것을 확인할 수 있지만 계속적으로 뷰를 업데이트하면 onCreateViewHolder는 더이상 로그에서 보이지않고 onBindViewHolder 메소드만 계속적으로 호출되어 데이터 바인딩만이 계속되고 있음을 확인할 수 있습니다. 

지금까지 리사이클러뷰 어댑터에 대해 알아보았습니다! 잘못 서술되어있는 부분등이 보이거나 문의사항 있을 시 덧글 부탁드립니다~. 감사합니다.

 

<참조>

 

Adapter  |  Android Developers

android.net.wifi.hotspot2.omadm

developer.android.com

https://developer.android.com/reference/androidx/recyclerview/widget/RecyclerView.ViewHolder

 

RecyclerView.ViewHolder  |  Android Developers

androidx.car.app.managers

developer.android.com

https://developer.android.com/guide/topics/ui/layout/recyclerview?hl=ko  

 

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

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

developer.android.com

 

https://stickode.tistory.com/40

 

[Java][Android] 리사이클러뷰 만들기

이번 포스팅에서는 리사이클러뷰를 만드는 방법을 알아보겠습니다. 리사이클러뷰란 ? 기존의 ListView을 보완하기위해 , ViewHolder를 통하여 뷰를 재사용하며 성능적인 면을 개선하고 , 커스터마이

stickode.tistory.com