Recycler View 파헤치기
RecyclerView란?
RecyclerView는 ListView의 발전된 형태로, 안드로이드 젯팩에 포함된 오브젝트이다. 공식사이트 스크롤은 거의 모든 앱에 필요한 형태이고, RecyclerView는 리소스를 효율적으로 사용함과 동시에 대단히 많은 일들을 behind the scene에서 처리해 주어 사용자가 앱 개발을 편하게 할 수 있게 해준다.
동작 원리 개관
RecyclerView는 혼자 작동하지는 않고 여러 작은 요소들과 함께 동작한다. LayoutManager, Adapter, Adapter 내부 ViewHolders, 데이터 원본 등등이다. 다음 그림을 참고하자.
각각이 하는 일은 다음과 같다.
-
LayoutManager: RecyclerView와 연결된 adapter에 명령(메쏘드들)을 내리는 중추
-
RecyclerView: ViewHolder 재활용
-
Adapter: 3가지 오버라이딩 메소드(onCreatViewHolder, onBindViewHolder, getItemCount) 및 ViewHolder Class를 갖고 있으며 각각이 역할이 있다.
하나씩 알아보도록 하자
RecyClerView 작성 순서
- 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>
- 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>
- 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);
}
// ...
}
- 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;
}
}
댓글남기기