Android (안드로이드)

[Android] 리사이클러뷰 사용법 / RecyclerView / 리사이클러뷰 아이템 추가

Oscar:) 2024. 1. 18. 15:10

 

 

이번 포스팅에서는 리사이클러뷰에 대해 알아보자.

 

 

 

✅ 목차

 

- 리사이클러뷰란?

 

- 리사이클러뷰 만들기

 

- 리사이클러뷰에 아이템 추가

 

 

 

리사이클러뷰 아이템 클릭 이벤트와

아이템 수정·삭제는 다음 포스팅에서 작성하겠다.

 

 

 

ArrayList에 대한 개념이 부족하다면 리사이클러뷰를 이해하기 어렵다.

혹시나 하는 마음에 ArrayList 관련 포스팅을 첨부한다.

 

 

[Java] 배열 Array (2) - ArrayList / ArrayList 메서드

배열에 대해 알아보았던 지난 포스팅에 이어서, 배열의 진화라고 볼 수 있는 ArrayList 에 대해 알아보자. ArrayList 시간의 흐름에 따라 기술은 계속 향상되기 마련이다. ArrayList는 기존의 배열의 단

oscarstory.tistory.com

 


 

 

리사이클러뷰란?

 

 

RecyclerView

*Recycle : 재활용하다

 

리사이클러뷰는 대량의 데이터를 효율적으로 표시할 수 있게끔 해주는 위젯이다.

 

ViewHolder 패턴을 적용하여 스크롤 시 View를 재활용한다.

ListView의 상위 호환 버전이라고 생각하면 된다.

 

말이 어렵지만, 그림을 보면 이해하기 쉽다.

 

 

ListView는 리스트 내 모든 View를 만들어서 띄운다.

RecyclerView는 화면에 보이는 부분만 만들어 놓고 데이터만 갈아 치우는 느낌이다.

 

껍데기는 동일하고, 데이터만 달라지는 View의 재활용이라 볼 수 있다.

 

 


 

리사이클러뷰 만들기

 

 

리사이클러뷰를 만들기 위해서는 아래 파일들이 필요하다.

 

 

- 리사이클러뷰 안에 들어갈 아이템 layout.xml

- 리사이클러뷰가 포함될 액티비티 전용 layout.xml

- 아이템 형식에 맞는 데이터 클래스.java

- 리사이클러뷰 Adapter.java

- 리사이클러뷰가 포함될 Activity.java

 

 

당연히 만드는 사람의 스타일에 따라 다르겠지만,

보통은 위 5개의 파일을 필요로 한다.

 

하나씩 차근차근 만들어보자.

 

 


 

 

리사이클러뷰 아이템에 해당하는 레이아웃을 만들어주자.

 

대충 다음과 같이 생겼다.

 

 

이름과 취미가 들어갈 아이템이다.

 

 

recyclerview_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    >
    
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:paddingVertical="15dp"
        >

        <TextView
            android:id="@+id/nameItemTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="20dp"
            android:text="이름"
            android:textColor="@color/black"
            />

        <TextView
            android:id="@+id/hobbyItemTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="20dp"
            android:text="취미"
            android:textColor="@color/black"
            />
        
    </LinearLayout>
    
    <View
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:background="@color/gray"
        />

</LinearLayout>

 

영역 지정은 각자 알아서 하기 바란다.

 

 

이름과 취미가 들어갈 TextView를 2개 만들고,

간단한 View를 만들어서 하단에 선을 그어줬다.

 

세로 스크롤 형태의 리사이클러뷰를 만들 것이기 때문에

최상위 View Group의 height는 "match_parent"로 지정하면 안 된다.

 

반대로 가로 스크롤 형태로 만든다면

최상위 View Group의 width는 "match_parent"로 지정하면 안 된다.

 

 


 

 

리사이클러뷰가 포함될 액티비티의 레이아웃 파일을 만들어준다.

 

이렇게 생겼다.

 

 

 

activity_recycler_view.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".Activity.RecyclerViewActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="8"
        />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="2"
        android:orientation="vertical"
        android:background="@color/gray"
        >

        <View
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_weight="1"
            />

        <Button
            android:id="@+id/itemAddButton"
            android:layout_width="150dp"
            android:layout_height="70dp"
            android:text="아이템 추가"
            android:textSize="18dp"
            android:textStyle="bold"
            android:layout_gravity="center"
            />

        <View
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_weight="1"
            />

    </LinearLayout>

</LinearLayout>

 

 

사실 이 xml 파일은 크게 중요한 점은 없다.

각자 앱에 알맞는 디자인을 하면 된다.

 

 


 

 

데이터 클래스를 만들어준다.

 

 

Student.java

public class Student {

    String name;
    String hobby;

    public Student(String name, String hobby) {

        this.name = name;
        this.hobby = hobby;

    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getHobby() {
        return hobby;
    }

    public void setHobby(String hobby) {
        this.hobby = hobby;
    }

}

 

 

학생들의 이름, 취미 데이터를 관리하는 데이터 클래스다.

 

name, hobby 변수를 선언하고

getter(), setter()를 만들어 주었다.

(이 예제에서 setter()는 사용하지 않는게 함정)

 

 


 

 

리사이클러뷰 어댑터를 만들어준다.

 

 

리사이클러뷰가 처음이라면 보통 어댑터 쪽이 제일 어려울 것이다.

문법적으로 강제되는 부분이 많아서 딱딱하게 느껴질 뿐이다.

 

어댑터의 기본적인 문법을 간단히 정리해보자.

 

 

RecyclerViewAdapter.java

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {

    ArrayList<Student> arrayList;

    @NonNull
    @Override
    public RecyclerViewAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_item, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerViewAdapter.ViewHolder holder, int position) {
        holder.onBind(arrayList.get(holder.getAdapterPosition()));
    }

    @Override
    public int getItemCount() {
        return arrayList.size();
    }

    public void setItem(ArrayList<Student> arrayList) {
        this.arrayList = arrayList;
        notifyDataSetChanged();
    }

    class ViewHolder extends RecyclerView.ViewHolder {

        TextView nameText;
        TextView ageText;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);

            nameText = itemView.findViewById(R.id.nameItemTextView);
            ageText = itemView.findViewById(R.id.hobbyItemTextView);

        }

        void onBind(Student student) {

            nameText.setText(student.getName());
            ageText.setText(String.valueOf(student.getHobby()));

        }

    }

}

 

 

● 어댑터는 RecyclerView.Adatper<ViewHolder>를 상속해야 한다.

 

 

● 리사이클러뷰에 바인딩할 ArrayList를 가지고 있어야 한다.

 

 

● 리사이클러뷰를 사용하는 곳(Activity,Fragment 등)에서

호출하여 리스트를 갱신할 수 있도록 함수를 만들어 준다.

 

본인은 setItem() 이라는 메서드를 만들어줬다.

ArrayList 변경을 notify() 해주는 부분이다.

 

생성자로 사용해도 무방하다.

 

 

● 다음 요소들을 가지고 있어야 한다.

 

- onCreateViewHolder()

ViewHolder를 생성하여 리턴해주는 메서드다.

위에서 만들어줬던 아이템 레이아웃 파일을 inflate하여 ViewHolder의 인수에 넣어준다.

 

 

- onBindViewHolder()

ViewHolder를 바인딩 해주는 메서드다.

 

View에 대한 작업을 여기서 해도 무방하지만, 우리는

ViewHolder의 onBind() 메서드에서 처리했기 때문에 메서드만 호출해주면 된다.

 

ViewHolder.getAdapterPosition() 메서드로

해당 아이템의 인덱스 값을 받아올 수 있다.

 

 

- getItemCount()

ArrayList의 size()를 리턴하는 메서드다.

 

 

- ViewHolder 클래스

아이템 레이아웃 파일의 View를 관리하는 곳이다.

 

생성자에서 View를 참조하고, 따로 메서드를 만들어서

데이터 클래스(Student)를 매개로 데이터를 처리해 주었다.

 

 

 


 

 

이제 리사이클러뷰가 포함될 액티비티를 작성해주자.

 

 

RecyclerViewActivity.java

public class RecyclerViewActivity extends AppCompatActivity {

    RecyclerView recyclerView;
    RecyclerViewAdapter adapter;
    ArrayList<Student> arrayList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recycler_view);

        // recyclerView, adapter, arrayList 초기화
        recyclerView = findViewById(R.id.recyclerView);
        adapter = new RecyclerViewAdapter();
        arrayList = new ArrayList<>();
        addList();
        
        // recyclerView, adapter 세팅
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setAdapter(adapter);
        adapter.setItem(arrayList);

    }
    
    // ArrayList에 하드코딩 데이터 추가
    void addList() {

        arrayList.add(new Student("오스카", "낚시"));
        arrayList.add(new Student("휴먼", "게임"));
        arrayList.add(new Student("샘", "빈둥대기"));
        arrayList.add(new Student("해리", "운동"));
        arrayList.add(new Student("나키", "장기"));
        arrayList.add(new Student("스텔라", "음주"));

    }
    
}

 

 

RecyclerView, Adapter, ArrayList 이렇게 3가지만 기억하면 된다.

3가지를 초기화 해주고, 세팅하는 부분으로 구분 지어놨다.

 

 

RecyclerView.setLayoutManager() 메서드로 레이아웃 매니저를 지정해준다.

여기서 가로 or 세로 스크롤을 지정할 수 있고, 그리드 타입으로 지정할 수도 있다.

 

RecyclerView.setAdapter() 메서드로 어댑터를 연결해준다.

 

어댑터에서 만들어준 setItem() 메서드에 ArrayList를 연결해주면 끝이다.

 

 

addList() 메서드는 하드코딩으로 데이터를 넣고 확인하기 위해 만들었다.

 

 


 

 

실행 결과

 

 

 

리사이클러뷰에 데이터가 잘 띄워졌다.

 

 


 

리사이클러뷰에 아이템 추가하기

 

 

위에서는 지정해둔 하드코딩 텍스트를 리스트에 추가하는 방식으로 진행했다.

 

사용자에게 입력 받은 값을 아이템으로 추가하는 방법을 알아보자.

 

미리 만들어둔 아이템 추가 버튼을 클릭하여 구현할 것이다.

 

 

버튼을 클릭하면 다이얼로그를 띄우고,

EditText에 입력 받은 값을 ArrayList에 추가하는 방식으로 진행하겠다.

 

 

public class RecyclerViewActivity extends AppCompatActivity {

    RecyclerView recyclerView;
    RecyclerViewAdapter adapter;
    ArrayList<Student> arrayList;
    Button itemAddButton;
    
    AlertDialog dialog;
    View dialogView;
    EditText nameEditText;
    EditText hobbyEditText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recycler_view);

        // recyclerView, adapter, arrayList 초기화
        recyclerView = findViewById(R.id.recyclerView);
        adapter = new RecyclerViewAdapter();
        arrayList = new ArrayList<>();
        
        // recyclerView, adapter 세팅
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setAdapter(adapter);
        adapter.setItem(arrayList);

        itemAddButton = findViewById(R.id.itemAddButton);
        
        dialogView = getLayoutInflater().inflate(R.layout.custom_dialog, null);
        nameEditText = dialogView.findViewById(R.id.dialogNameEditText);
        hobbyEditText = dialogView.findViewById(R.id.dialogHobbyEditText);
        dialogSubmitButton = dialogView.findViewById(R.id.dialogSubmitButton);
        
        // 아이템 추가 버튼 클릭
        itemAddButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                showDialog();
            
            }
        });

    }
    
    // 다이얼로그 띄우는 메서드
    void showDialog() {

        nameEditText.setText("");
        hobbyEditText.setText("");

        dialog = new AlertDialog.Builder(RecyclerViewActivity.this)
                .setView(dialogView)
                .setPositiveButton("완료", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {

                        String name = nameEditText.getText().toString();
                        String hobby = hobbyEditText.getText().toString();

                        arrayList.add(new Student(name, hobby));
                        adapter.setItem(arrayList);
                        
                        ((ViewGroup)dialogView.getParent()).removeView(dialogView);

                    }
                })
                .create();

        dialog.show();

    }
    
}

 

 

뭐가 많아 보이지만 별거 없다.

사용자에게 데이터를 어떻게 입력 받을지는 각자 앱에 맞게 구성하면 그만이다.

 

핵심은 딱 2가지다.

- ArrayList의 데이터를 변경해주는 것

- Adapter에 알리는 것

 

데이터 클래스와 어댑터를 만들어 놓은 이후부터는

위 2가지만 해주면 리사이클러뷰가 업데이트 된다는 것만 알면 된다.

 

 


 

결과는 다음과 같다.

 

 

아이템이 성공적으로 추가된다.

 

 


 

 

리사이클러뷰는 ArrayList와 Adapter에 대한 이해만 충분하다면

그리 어렵진 않다고 생각한다.

 

만약, 아직도 이해가 어렵다면 위 2개를 세심히 공부하기 바란다.

 

 

리사이클러뷰 아이템 클릭 이벤트와

아이템 수정·삭제는 다음 포스팅에서 다뤄보겠다.