본문 바로가기
Android/안드로이드 기본지식

[Android] Recycler View 사용하기

by 붕어사랑 티스토리 2022. 6. 15.
반응형

https://developer.android.com/guide/topics/ui/layout/recyclerview

 

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

RecyclerView로 동적 목록 만들기   Android Jetpack의 구성요소 RecyclerView를 사용하면 대량의 데이터 세트를 효율적으로 표시할 수 있습니다. 개발자가 데이터를 제공하고 각 항목의 모양을 정의하면 R

developer.android.com

1. Recycler View란?

데이터를 리스트로 나타내주는 뷰 이다. 아니 그럼 리스트뷰 쓰면 되지 왜 Recycler View를 쓰는가?

그 이유는 리스트뷰가 가지고 있던 성능문제를 Recycler View는 해결했기 때문.

 

이름에 Recycler이라는 내용이 들어간 것만 봐도 자원을 효율적으로 재활용하여 동작한다.

 

이 Recycler View는 스크롤 될 때 표시된 데이터를 destroy하지 않는다. 대신 이를 재활용한다. 그렇게 해서 성능을 대폭 향상시킬 수 있다.

 

 

2. Key Classes

다음으로 Recycler View를 이용할 때 알아야 할 핵심 개념들을 익혀보자

 

  • Recycler View - 리사이클러 뷰는 그 자체로 ViewGroup이자 View이다. 고로 xml에 그냥 뷰 처럼 넣어주면 된다
  • View Holder - 리스트에 나올 개별 element들은 View Holder라고 정의된다. View Holder는 처음 생성될 때 아무 데이터도 가지고 있지 않다. RecyclerView가 나중에 data를 binding 해 준다. ViewHolder를 사용하려면 RecyclerView.ViewHolder를 상속받아야 한다.
  • Adapter - RecyclerViewViewHolder에 데이터를 바인딩 할 때 사용하는 클래스이다. RecyclerView.Adapter를 상속받아 구현한다
  • LayoutManager - 레이아웃 매니저는 각 element들을 리스트에 정렬해주는 역할을 한다. 이는 RecyclerView 라이브러리의 레이아웃 매니저를 사용할 수 있고 또는 직접 커스텀하여 구현 가능하다. 레이아웃 매니저는 LayoutManager 클래스를 기본으로 한다

 

 

3. 리사이클러 뷰 구현하는 절차

리사이클러 뷰를 사용하려면 다음과 같은 항목을 진행해야 한다

 

  • 먼저 리스트나 grid가 어떤 look을 가질 지 결정한다
  • 표현될 각각의 element들이 어떤 디자인을 가질지 결정한다. 그리고 이 디자인을 기반으로 ViewHodler 클래스를 정의한다. 새로 정의한 ViewHolder는 list되는 아이템의 기능적인 요소를 모두 담고있어야 한다. ViewHolder는 View의 wrapper이며, 이 뷰는 RecyclerView에 의해 관리된다.
  • 마지막으로 Adapter를 정의하여 데어티어 ViewHolder를 바인딩 해 준다.

 

 

4. 레이아웃 매니저 선택

리사이클러뷰에 나오는 아이템들은 LayoutManager에 의해 정렬된다. 이 레이아웃 매니저는 직접 정의할 수 도 있고 아니면 이미 정의된 것을 사용해도 된다. 리사이클러뷰는 세가지의 레이아웃 매니저를 제공한다.

 

  • LinearLayoutManager - 한쪽 방향으로 아이템을 나타내주는 1차원 레이아웃 매니저
  • GridLayoutManager - 격자무늬로 아이템을 나타내주는 2차원 평면의 레이아웃 매니저
    - 만약 격자무니가 vertically하게 배치되면, 그리드 레이아웃 매니저는 각각의 row의 모든 elements들을 같은 width, height로 나타내려 한다. 그러나 각각의 row는 다른 height을 가질 수 있다
    - 만약 격자무늬가 horizontally하게 배치되면, 그리드레이아웃 매니저는 각각의 column들을 같은 width, height로 나타내려 한다. 각각의 column들은 다른 width를 가질 수 있다
  • StaggerGridLayoutManager - 그리드 레이아웃 매니저와 비슷하다. 그러나 같은 row나 column에 있는 element에게 같은 width, height를 요구하지 않는다

 

 

 

5. 어댑터와 뷰홀더 구현

어떤 레이아웃으로 할 지 결정하였으면 다음으로 Adapter와 ViewHolder의 구현이 필요하다.

 

아래는 어댑터를 구현할 때 반드시 오바리이딩 해야하는 메소드 들이다

  • onCreateViewHolder() - RecyclerView가 새로운 ViewHolder를 생성할 때 마다 부르는 함수이다. 이 메소드는 뷰홀더를 생성하고 initialize 한다. 그러나 뷰홀더에 특정한 데이터를 채우지는 않는다.
  • onBindViewHolder() - RecyclerView가 뷰홀더에 새로운 데이터를 bind할 떄 마다 호출된다. 이 메소드는 적절한 데이터를 가져와서 뷰홀더의 레이아웃에 채운다. 예를들어 RecyclerView가 이름목록을 나타낼 때, 이 메소드는 적절한 이름을 리스트에서 찾아와서 뷰홀더의 TextView에 넣어준다
  • getItemCount() : 리사이클러뷰가 데이터셋의 크기를 얻어올 때 호출된다. 리사이클러뷰가 데이터 크기를 확인해 더이상 데이터를 호출할 수 없는 상황을 파악하는데 사용한다.

 

 

아래 예제는 공식문서 가이드를 참고하여 만들어본 예제이다.

 

이미지를 횡스크롤로 리스트 해주는 코드임

 

 

먼저 element가 될 xml을 정의해주자

 

image_view_holder.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/myImageView"/>

</LinearLayout>

그다음에 어댑터를 정의해준다.

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
    private Drawable[] localDataSet;

    public static class ViewHolder extends RecyclerView.ViewHolder {
        private final ImageView imageView;
        public ViewHolder(View view) {
            super(view);
            imageView = (ImageView) view.findViewById(R.id.myImageView);
        }

        public ImageView getImageView() {
            return imageView;
        }
    }

    public MyAdapter(Drawable[] dataSet) {
        localDataSet = dataSet;
    }

    // Create new views (invoked by the layout manager)
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        // Create a new view, which defines the UI of the list item
        View view = LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.image_view_holder, viewGroup, false);

        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        holder.getImageView().setImageDrawable(localDataSet[position]);
    }

    @Override
    public int getItemCount() {
        return localDataSet.length;
    }

}

어댑터와 리이넝 매니저를 등록해주면 리사이클러 뷰에 나타난다.

public class MainActivity extends AppCompatActivity {

    Drawable[] drawables = new Drawable[2];

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

        RecyclerView recView = findViewById(R.id.myRecyclerView);
        initDataSet();
        MyAdapter myAdapter = new MyAdapter(drawables);
        recView.setAdapter(myAdapter);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getApplicationContext());
        linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        recView.setLayoutManager(linearLayoutManager);
    }

    public void initDataSet() {
        for (int i = 0; i <2; i++) {
            int id = getResources().getIdentifier("bounguh"+i, "drawable", getPackageName());
            drawables[i] = ResourcesCompat.getDrawable(getResources(), id, null);
        }
    }
}

 

반응형

댓글