Recycler View 파헤치기

4 분 소요

RecyclerView란?

RecyclerView는 ListView의 발전된 형태로, 안드로이드 젯팩에 포함된 오브젝트이다. 공식사이트 스크롤은 거의 모든 앱에 필요한 형태이고, RecyclerView는 리소스를 효율적으로 사용함과 동시에 대단히 많은 일들을 behind the scene에서 처리해 주어 사용자가 앱 개발을 편하게 할 수 있게 해준다.

동작 원리 개관

RecyclerView는 혼자 작동하지는 않고 여러 작은 요소들과 함께 동작한다. LayoutManager, Adapter, Adapter 내부 ViewHolders, 데이터 원본 등등이다. 다음 그림을 참고하자.

image

각각이 하는 일은 다음과 같다.

  • LayoutManager: RecyclerView와 연결된 adapter에 명령(메쏘드들)을 내리는 중추

  • RecyclerView: ViewHolder 재활용

  • Adapter: 3가지 오버라이딩 메소드(onCreatViewHolder, onBindViewHolder, getItemCount) 및 ViewHolder Class를 갖고 있으며 각각이 역할이 있다.

하나씩 알아보도록 하자

RecyClerView 작성 순서

  1. Layout에 RecyclerView 배치

간단히 RecyclerView 오브젝트를 배치한다.

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_numbers"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</FrameLayout>
  1. Recycle에 사용될 (ViewHolder생성용) 레이어웃을 생성한다. Layout 폴더 밑에 xml생성 이용. 이 레이아웃이 복제되어 리스트로 사용될 것이다. 2개의 텍스트뷰를 생성해 보자. 이름은 list_item.xml로 짓자.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="16dp">

    <TextView
        android:id="@+id/text_view_1"
        style="@style/TextAppearance.AppCompat.Title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
	/>

	    <TextView
        android:id="@+id/text_view_2"
        style="@style/TextAppearance.AppCompat.Title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
	/>

</FrameLayout>
  1. Main Activity 코드에 아래와 같이 reclyclerView 에 LayoutManager와 adapter 를 연결한다.
public class MyActivity extends Activity {
    private RecyclerView recyclerView;
    private RecyclerView.Adapter mAdapter;
    private RecyclerView.LayoutManager layoutManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.my_activity);
        recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);

        // 이 옵션은 레이아웃 사이즈가 바뀌지 않는다는 걸 미리 알고 있을 때 사용하면 좋다.
        recyclerView.setHasFixedSize(true);

        // use a linear layout manager
        layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);

        // myDataset은 현재 비어 있다. 
        mAdapter = new MyAdapter(myDataset);
        recyclerView.setAdapter(mAdapter);
    }
    // ...
}
  1. Custom adapter 클래스를 새로 만든다. Adapter가 override method를 통해 다음의 3가지일을 한다. XML에서 새 아이템이 생성될 자리(recyclerView)를 찾아 View를 만든 후 그 view를 바탕으로 Viewholder를 만들어 return하고(onCreateViewHolder), 아이템을 원본 데이터와 연결하여 화면에 뿌리고(onBindViewHolder), 아이템이 몇 개인지 반환하고 (getItemCount)

// RecyclerView.Adapter클래스를 상속받는 Custom Adapter클래스를 새로 만들자. 
// onBindViewHolder에서 사용할 inner class인 Custom ViewHolder 를 인자로 갖는다. 
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {

    private String[] mDataset;

    // 커스텀 ViewHolder class를 생성하자. 
    public static class MyViewHolder extends RecyclerView.ViewHolder {
        public TextView textView1;
        public TextView textView2;
        // Constructor 
        // 복제하고 싶은 list_item 레이아웃이 2개의 텍스트뷰를 가졌으므로 마찬가지로 2개의 텍스트뷰를 생성하고 각각 findViewById로 찾아서 assign한다. 
        public MyViewHolder(TextView v) {
            super(v);
            textView1 = (TextView) v.findViewById(R.id.textView1);
            textView2 = (TextView) v.findViewById(R.id.textView2);
        }
    }

    // 커스텀 어답터 생성자.
    public MyAdapter(String[] myDataset) {
        mDataset = myDataset;
    }

    // 3가지 Override Method를 작성해야 한다. 
    // 먼저 onCreateViewHolder. ViewGroup parent는 xml에서 만들어 놓은 recyclerView다. 
    @Override
    public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
                                                   int viewType) {
        // recyclerView(parent) 내에 새로운 view를 만들자. 
        // blue print는 아까 만들어 놓은 list_item.xml이다. (R.layout.list.item)
        TextView v = (TextView) LayoutInflater.from(parent.getContext())
                .inflate(R.layout.list_item, parent, false);
        ...
        // 해당 뷰를 이용해 뷰홀더 인스턴스를 만든다.
        // 이를 통해 뷰홀더 내 textView1, 2 와 list_item내 text_view_1, 2 가 연결된다. 
        // 만들어진 뷰홀더를 반환한다. 
        MyViewHolder vh = new MyViewHolder(v);
        return vh;
    }

    // onBindViewHolder를 통해 데이터를 set한다.  
    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {

        holder.textView1.setText(mDataset[position]);
        holder.textView2.setText(mDataset[position]);
    }

    // adapter에 의해 가장 먼저 실행될 메쏘드. 
    // 아이템의 개수를 반환한다. 
    @Override
    public int getItemCount() {
        return mDataset.length;
    }
}

댓글남기기