본문 바로가기
~2024.10

[Android] ListView/RecyclerView 정리(작성 중)

by HJfan 2024. 3. 16.

▶ 본 게시물은 강의 및 설명의 목적이 아닌 개인 학습과 복습 목적의 게시물이기에 틀린 정보가 존재할 수 있습니다.

 

>참조 문서 및 강의 목록<

- https://meal-coding.tistory.com/29

- 깡쌤의 안드로이드 앱 프로그래밍 with 자바 강의(유료)

 

[Android] 홍드로이드 기초 강의 - 리사이클러뷰(RecyclerView)

1. 안드로이드 리사이클러뷰(RecyclerView) "수많은 데이터의 집합을 지정된 영역 내에서 유연하게(flexible) 표시되도록 만들어주는 위젯"입니다. 안드로이드 개발자 문서에 작성된 리사이클러뷰(Recyc

meal-coding.tistory.com


01. ListView / RecyclerView

안드로이드 프로그래밍에서 목록과 같은 화면을 구현하는 방법은 주로 2가지가 있다.

ListView(플랫폼 API)를 사용하는 방법과 RecyclerView(androidx)를 사용하는 방법이다.

*플랫폼 API : 안드로이드 os가 제공하는 기본적인 함수와 기능들의 집합

*androidx : Android Support Library의 후속으로, 안드로이드 JetPack의 일부. 최신 컴포넌트, 도구, 유틸리티 등을 제공

 

항목을 나열하기 위해서 ListView와 RecyclerView 모두 Adapter를 사용해야 한다는 공통점이 있지만,

ListView는 Adapter만 필요한 반면, RecyclerView를 사용하기 위해서는 ViewHolder, Adapter, LayoutManager,

ItemDecoration(옵션), ItemAnimation(옵션) 요소들이 추가적으로 필요하다.

*옵션 : 필수적인 요소는 아니지만, 사용하면 유용한 요소

 

RecyclerView는 필요한 요소가 많아진 만큼, 제한된 기능을 제공하던 ListView의 단점들을 보완하여

사용자에게 보다 나은 뷰 재사용 및 복잡한 레이아웃 구현에 있어 이점을 줄 수 있다.


02. 차이점

ListView는 스크롤 할 때마다 화면에서 사라지는 가장 위의 item을 삭제하고, 가장 아래에 새로운 item을 생성하는

방식으로 구현되었다. 이 과정에서 각 항목의 View 객체가 반복적으로 생성/삭제될 수 있고, 이는 자원의 사용량을

증가시켜 성능에 영향을 줄 수 있다. 그에 비해 RecyclerView는 사라진 항목의 View를 삭제하는 대신 재활용하여

가장 아래로 이동시킨다. 즉, 항목의 데이터만 수정하고 View 자체는 재활용하는 구조로 되어 있기 때문에, View

객체의 생성/삭제로 인한 비용(cost)를 크게 절약할 수 있다. 이 재활용 매커니즘은 RecyclerView의 성능을 크게

향상시키는 핵심 요소이다.

 

이미지 출처 :&nbsp;https://medium.com/mindorks/diffutils-improving-performance-of-recyclerview-102b254a9e4a

 

 

또 ListView는 기본적으로 item을 수직으로만 나열할 수 있다. 수평 방향으로 나열하는 것이 불가능한 것은 아니지만

이를 위해서는 ListView를 상당히 수정하거나, 다른 View를 사용해야만 한다. 이와 대조적으로 RecyclerView는

LayoutManager를 통해 수직은 물론 수평 혹은 격자(grid) 형태로 item을 나열할 수 있는 유연성을 제공한다.

LayoutManager는 RecyclerView의 item 배치와 스크롤 동작을 관리하며, 개발자가 런타임에 동적으로 변경할 수

있게 함으로써 더욱 다양한 사용 사례를 지원한다.


03. RecyclerView  요소 - 필수

ㆍAdapter

   >데이터 컬렉션과 RecyclerView의 각 항목을 연결하는 역할을 한다. 이는 데이터를 가져와서

     각 항목에 해당하는 view를 생성하고, 데이터를 그 뷰에 바인딩하는 과정을 담당한다.


04. RecyclerView 요소 - 옵션

위에서 설명한 요소들과 달리 ItemDecoration과 ItemAnimation은 필수가 아닌 옵션 요소들이다.

우선 ItemDecoration에서 제공하는 3가지 함수를 살펴보자.

ㆍonDraw

   >호출 시점 : Adapter가 만든 item을 LayoutManager가 화면에 배치하기 "전에"

                     (주로 background로 사용되는 것 같음)

ㆍonDrawOver

   >호출 시점 : Adapter가 만든 item을 LayoutManager가 화면에 배치한 "후에"

ㆍgetItemOffsets

   >호출 시점 : 각 item을 배치할 때 호출(item 하나 하나를 꾸밀 때 사용함)

*위 3가지 함수들은 추상 함수가 아니기에, 반드시 오버라이드 받는 것이 아니라 필요한 함수만 쓰면 된다.

 

ItemDecoration에서 제공하는 함수를 사용했다면, RecyclerView에 적용시켜주는 과정이 필요하다.

그 과정을 위한 코드는 아래 형태와 같다.

recyclerView.addItemDecoration(new MyItemDecoration());

//깡쌤 안드로이드 앱 프로그래밍 with 자바 강의 중 일부 발췌

05. 실습(예제 포함)

 

05-1. 빌드 종속성 추가(build.gradle 파일)

 

 

05-2. 실습용 레이아웃 구현(activity_main.xml)

<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=".MainActivity">

    <Button
        android:id="@+id/addButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="ADD" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

recyclerView를 사용하는 것이 목적이라 단순하게 버튼 하나와 리사이클뷰 하나만 배치한다.

버튼을 터치할 때마다, "Hello, World 1", "Hello, World 2"...처럼 문자열을 리스트에 출력되게 할 것.

 

 

05-3. 리스트 각각의 목록을 구성하는 xml 파일 생성(item_view.xml)

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/itemTextView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="16dp"
    android:textSize="18sp" />

RecyclerView 사용을 위해선 위에서 언급한 Hello, World 1처럼 각각의 항목을 설정하는 파일이 필요하다.

 

 

05-4. Adapter와 ViewHolder 설정(MyAdapter.java)

package com.example.lab_recycler2;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
    private ArrayList<String> mDataset;

    public static class MyViewHolder extends RecyclerView.ViewHolder {
        public TextView textView;
        public MyViewHolder(View itemView) {
            super(itemView);
            textView = itemView.findViewById(R.id.itemTextView);
        }
    }

    public MyAdapter(ArrayList<String> myDataset) {
        mDataset = myDataset;
    }

    @NonNull
    @Override
    public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_view, parent, false);
        return new MyViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        holder.textView.setText(mDataset.get(position));
    }

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

    public void addItem(String text) {
        mDataset.add(text);
        notifyItemInserted(mDataset.size() - 1);
    }
}

<설명 추가 예정>

 

 

05-5. MainActivity.java

package com.example.lab_recycler2;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.View;
import android.widget.Button;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {
    private RecyclerView recyclerView;
    private MyAdapter mAdapter;
    private ArrayList<String> myDataset = new ArrayList<>();
    private int count = 1;

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

        recyclerView = findViewById(R.id.recyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        mAdapter = new MyAdapter(myDataset);
        recyclerView.setAdapter(mAdapter);

        Button addButton = findViewById(R.id.addButton);
        addButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String item = "Hello, World " + count++;
                mAdapter.addItem(item);
            }
        });
    }
}

<설명 추가 예정>

 

05-6. 결과