https://developer.android.com/guide/topics/ui/layout/recyclerview
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 - RecyclerView가 ViewHolder에 데이터를 바인딩 할 때 사용하는 클래스이다. 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);
}
}
}
'Android > 안드로이드 기본지식' 카테고리의 다른 글
[Android] sp에서 dp로 변환, dp에서 sp로 변환 (0) | 2022.07.13 |
---|---|
[Android] dp, sp, dpi, pt용어정리 (0) | 2022.07.01 |
[Android] Service 배우기 (0) | 2022.05.25 |
[Android] Camera2 배우기 (2) | 2022.05.13 |
[Android] Canvas를 이용하여 UI 그리기 (0) | 2022.04.14 |
댓글