어댑터(Adapter)는 Android에서 UI 요소와 데이터를 연결하는 역할을 하는 중요한 컴포넌트입니다.
일반적으로 RecyclerView, ListView, GridView 등의 뷰에서 사용되며, 뷰와 데이터 사이의 중개자 역할을 합니다.
어댑터의 주요 역할:
- 데이터와 뷰 연결:
- 어댑터는 데이터를 UI 요소와 연결합니다. 예를 들어, 리스트 항목에 표시할 데이터를 준비하고, 이를 각 항목에 대한 뷰에 바인딩합니다.
- 데이터의 구조적 표현:
- 어댑터는 주어진 데이터 집합(배열, 리스트 등)을 UI에서 사용할 수 있는 형식으로 변환합니다. 예를 들어, 배열의 각 항목을 RecyclerView의 항목으로 변환하고 표시합니다.
- 아이템 뷰 관리:
- 어댑터는 각 항목을 ViewHolder를 사용하여 관리하고, 뷰의 재사용을 최적화합니다. RecyclerView에서 onCreateViewHolder()와 onBindViewHolder() 메서드를 사용하여 새로운 뷰를 생성하거나 기존 뷰를 재사용합니다.
- UI와 데이터 동기화:
- 어댑터는 UI에서 데이터 변경을 반영하고, 데이터가 바뀌면 UI를 자동으로 업데이트합니다. 예를 들어, notifyDataSetChanged()를 호출하여 데이터 변경 시 UI를 새로고침합니다.
1. 어뎁터 상속
package com.marurun66.simplememo.adapter;
import androidx.recyclerview.widget.RecyclerView;
public class MemoAdapter extends RecyclerView.Adapter {
//1.어뎁터를 상속 받는다.
}
2. 뷰 홀더 클래스 만들기
public class MemoAdapter extends RecyclerView.Adapter {
//1.어뎁터를 상속 받는다.
//2.뷰 홀더 클래스를 만든다.
public class ViewHolder extends RecyclerView.ViewHolder {
TextView txtTitle;
TextView txtBody;
ImageView imageDelete;
public ViewHolder(@NonNull View itemView) {
super(itemView);
txtTitle=itemView.findViewById(R.id.txtTitle);
txtBody=itemView.findViewById(R.id.txtBody);
imageDelete=itemView.findViewById(R.id.imageDelete);
}
}
}
RecyclerView와 ViewHolder
RecyclerView는 많은 데이터를 효율적으로 표시할 수 있는 뷰입니다. 하지만 많은 아이템을 리스트로 표시할 때, 각각의 아이템을 findViewById로 매번 찾는 방식은 성능상 문제가 될 수 있습니다. 이를 해결하기 위해 뷰 홀더 패턴을 사용합니다.
역할
- 뷰 홀더는 각각의 아이템을 나타내는 뷰를 저장하는 객체입니다.
- 각 아이템의 뷰를 한 번만 찾고 이후에는 그 뷰를 재사용할 수 있도록 합니다. 즉, 뷰 홀더가 뷰 객체를 캐시하여 효율적으로 작업할 수 있습니다.
작동 원리
- 뷰 홀더 생성: onCreateViewHolder() 메서드에서 뷰를 생성하고, 이 뷰를 뷰 홀더에 저장합니다.
- 데이터 바인딩: onBindViewHolder() 메서드에서 데이터를 뷰 홀더에 바인딩합니다. 각 아이템에 대한 뷰를 재사용하기 때문에 성능이 개선됩니다.
3. RecyclerView.Adapter에 뷰 홀더 전달
public class MemoAdapter extends RecyclerView.Adapter<MemoAdapter.ViewHolder> {
//1.어뎁터를 상속 받는다. //3.만든 뷰 홀더를 적어준다.
//2.뷰 홀더 클래스를 만든다.
public class ViewHolder extends RecyclerView.ViewHolder {
TextView txtTitle;
TextView txtBody;
ImageView imageDelete;
public ViewHolder(@NonNull View itemView) {
super(itemView);
txtTitle=itemView.findViewById(R.id.txtTitle);
txtBody=itemView.findViewById(R.id.txtBody);
imageDelete=itemView.findViewById(R.id.imageDelete);
}
}
}
MemoAdapter.ViewHolder는 MemoAdapter 클래스 내에 정의된 ViewHolder 클래스를 의미합니다.
이 ViewHolder 클래스는 각 항목의 UI 요소를 관리하는 역할을 합니다.
MemoAdapter.ViewHolder를 RecyclerView.Adapter에 전달!
4. 메서드 오버라이드
public class MemoAdapter extends RecyclerView.Adapter<MemoAdapter.ViewHolder> {
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return null;
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
}
@Override
public int getItemCount() {
return 0;
}
//1.어뎁터를 상속 받는다. //3.만든 뷰 홀더를 적어준다.
//2.뷰 홀더 클래스를 만든다.
public class ViewHolder extends RecyclerView.ViewHolder {
TextView txtTitle;
TextView txtBody;
ImageView imageDelete;
public ViewHolder(@NonNull View itemView) {
super(itemView);
txtTitle=itemView.findViewById(R.id.txtTitle);
txtBody=itemView.findViewById(R.id.txtBody);
imageDelete=itemView.findViewById(R.id.imageDelete);
}
}
}
5. 클래스 멤버 변수와 생성자
public class MemoAdapter extends RecyclerView.Adapter<MemoAdapter.ViewHolder> {
//5.이 어댑터 클래스의 멤버 변수와 생성자 만들기
Context context;
ArrayList<Memo> arrayList;
public MemoAdapter(Context context, ArrayList<Memo> arrayList) {
this.context = context;
this.arrayList = arrayList;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return null;
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
}
@Override
public int getItemCount() {
return 0;
}
//1.어뎁터를 상속 받는다. //3.만든 뷰 홀더를 적어준다. //4. 오버라이드
//2.뷰 홀더 클래스를 만든다.
public class ViewHolder extends RecyclerView.ViewHolder {
TextView txtTitle;
TextView txtBody;
ImageView imageDelete;
public ViewHolder(@NonNull View itemView) {
super(itemView);
txtTitle=itemView.findViewById(R.id.txtTitle);
txtBody=itemView.findViewById(R.id.txtBody);
imageDelete=itemView.findViewById(R.id.imageDelete);
}
}
}
6.상속받은 3개의 메서드 구현
public class MemoAdapter extends RecyclerView.Adapter<MemoAdapter.ViewHolder> {
//5.이 어댑터 클래스의 멤버 변수와 생성자 만들기
Context context;
ArrayList<Memo> memoArrayList;
public MemoAdapter(Context context, ArrayList<Memo> arrayList) {
this.context = context;
this.memoArrayList = arrayList;
}
//6.아래 상속받은 3개 함수를 구현한다.
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view=LayoutInflater.from(parent.getContext()).inflate(R.layout.memo_row,parent,false);
return new MemoAdapter.ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Memo memo = memoArrayList.get(position);
holder.txtTitle.setText(memo.title);
holder.txtBody.setText(memo.body);
}
@Override
public int getItemCount() {
return memoArrayList.size();
}
//1.어뎁터를 상속 받는다. //3.만든 뷰 홀더를 적어준다. //4. 오버라이드
//2.뷰 홀더 클래스를 만든다.
public class ViewHolder extends RecyclerView.ViewHolder {
TextView txtTitle;
TextView txtBody;
ImageView imageDelete;
public ViewHolder(@NonNull View itemView) {
super(itemView);
txtTitle=itemView.findViewById(R.id.txtTitle);
txtBody=itemView.findViewById(R.id.txtBody);
imageDelete=itemView.findViewById(R.id.imageDelete);
}
}
}
1. onCreateViewHolder()
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.memo_row, parent, false);
return new MemoAdapter.ViewHolder(view);
}
- 목적: RecyclerView에서 각 항목을 위한 뷰를 생성하는 메서드입니다.
- onCreateViewHolder()는 RecyclerView가 새로운 아이템 뷰를 필요로 할 때마다 호출됩니다.
- 이 메서드는 새로운 ViewHolder 객체를 생성하여 RecyclerView.ViewHolder에 해당하는 뷰를 초기화하고 반환합니다.
- 인자:
- parent: 뷰가 삽입될 부모 뷰 그룹.
- viewType: RecyclerView에서 다양한 뷰 유형을 처리할 수 있지만, 여기에서는 사용되지 않음.
- 반환값: 새로운 뷰 홀더 객체를 반환합니다. 이 뷰 홀더는 각 아이템을 표시하는 데 사용될 레이아웃을 포함하고 있습니다.
2. onBindViewHolder()
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Memo memo = memoArrayList.get(position);
holder.txtTitle.setText(memo.title);
holder.txtBody.setText(memo.body);
}
- 목적: 각 아이템에 대한 데이터를 뷰 홀더에 바인딩하는 메서드입니다.
- onBindViewHolder()는 RecyclerView가 화면에 표시할 데이터 항목을 뷰 홀더에 바인딩할 때 호출됩니다. 즉, RecyclerView의 각 항목을 화면에 표시하기 위해 뷰 홀더와 데이터를 연결하는 작업을 합니다.
- 인자:
- holder: 데이터를 바인딩할 대상인 ViewHolder 객체입니다. 이 객체는 onCreateViewHolder()에서 생성된 뷰 홀더입니다.
- position: 바인딩할 데이터의 위치(인덱스)입니다. 이 값에 따라 memoArrayList에서 해당 위치의 데이터를 가져옵니다.
- 동작:
- memoArrayList.get(position)을 사용하여 해당 항목의 Memo 객체를 가져오고, 이를 holder의 뷰에 바인딩합니다.
- 예를 들어, txtTitle에 memo.title 값을, txtBody에 memo.body 값을 설정합니다.
3. getItemCount()
@Override
public int getItemCount() {
return memoArrayList.size();
}
- 목적: RecyclerView의 아이템 개수를 반환하는 메서드입니다.
- 이 메서드는 RecyclerView가 표시해야 할 항목의 개수를 알려줍니다. 이 개수는 RecyclerView가 데이터를 로드하거나 스크롤할 때 중요한 역할을 합니다.
- 반환값: memoArrayList.size()를 반환하여, 어댑터에 제공된 memoArrayList의 크기(아이템 수)를 반환합니다.
요약
- onCreateViewHolder()는 새로운 항목 뷰를 생성합니다.
- onBindViewHolder()는 데이터를 각 항목에 바인딩합니다.
- getItemCount()는 RecyclerView가 보여야 할 항목의 개수를 반환합니다.
이 세 메서드는 RecyclerView가 데이터를 효율적으로 표시할 수 있도록 도와주는 핵심적인 메서드들입니다.