티스토리 뷰
[Android] RecyclerView는 왜 쓰나요? DiffUtil은 뭐고 ListAdapter는 또 뭔가요?
weekyear 2020. 12. 13. 01:40Todo 리스트 앱을 만들면서 ListView를 쓰다가 막상 좀 찾아보니 RecyclerView가 더 많이 쓰인다는 것을 알게 되었다. 그리고 막상 써보니 맘처럼 쉽게 사용하기가 어려웠다. 그래서 아 이거 제대로 알고 쓰는 거 아니면 나중에 일이 더 커지겠는데 싶어서 제대로 공부해보고 쓰기로 마음먹고 이렇게 블로그를 들어와 포스팅을 하기 시작했다.
어떤 글에서나 쓰는 거지만 이 글은 제가 공부한 걸 제가 마음대로 써재기는 글인거지. 공부용으로는 전혀 도움이 안 됨을 미리 밝힙니다.
1. RecyclerView는 왜 쓰나요?
우선 RecyclerView 이전에 ListView가 있었음을 기억하자. 보통 앱을 구현하면서 ListView를 사용하는 경우에는 같은 item_layout.xml을 활용하는 경우가 많은데, 10개의 item이 있을 경우 findViewById()를 10번을 수행하게 된다. 그래서 RecyclerView를 활용하면서 쓰는 ViewHolder를 통해 findViewById에 의한 성능 이슈를 해결하기 위해서라고 한다.
이 외에도 LayoutManager나 ItemDecoration을 활용해서 리스트를 꾸미는데도 활용한다.
1-1. Adapter가 하는 맡은 역할 (번외)
Adapter는 ListView나 App의 특정 데이터와 RecyclerView의 view를 Bind하는 것을 도와준다. RecyclerView의 Adapter의 경우에는 View 객체를 재사용하기 위해 ViewHolder 객체를 생성해주는 역할을 맡기도 한다.
일반적인 RecyclerView의 Adapter의 경우, 전체 리스트 데이터를 통째로 갱신해야 할 때, 100개의 항목이 있다면 100개 모두 업데이트된다. 바뀌는 항목도 있지만 바뀌지 않는 항목이 더 많다면 100개의 항목을 모두 바꾸는 건 꽤나 비효율적일 것이다. 이를 위해 DiffUtil이 있다.
2. DiffUtil은 뭐야??
공식 문서에 따르면 DiffUtil은 기존의 리스트와 업데이트 된 리스트의 차이를 계산하고 실제로 변환할 리스트 아이템들의 결과를 반환하는 유틸리티 클래스라고 나와있다. 주로 RecyclerView Adapter의 업데이트를 계산하는 데 사용되고 ListAdapter와 AsyncListDiffer에서 DiffUtil을 활용해서 차이점을 계산한다.
DiffUtil 활용 방법
DiffUtil을 활용하기 위해서는 DiffUtil.Callback()을 구현해야 한다. Adapter안에 구현하였다.
(Todo는 그냥 임의의 타입으로 생가해달라)
1
2
3
4
5
6
7
8
9
10
|
public static DiffUtil.ItemCallback<Todo> DIFF_CALLBACK = new DiffUtil.ItemCallback<Todo>() {
@Override
public boolean areItemsTheSame(@NonNull Todo oldItem, @NonNull Todo newItem) {
return oldItem.id == newItem.id;
}
@Override
public boolean areContentsTheSame(@NonNull Todo oldItem, @NonNull Todo newItem) {
return oldItem.equals(newItem);
}
};
|
cs |
각 함수는 다음과 같은 의미를 가진다.
- areItemsTheSame() : 두 아이템이 동일한 아이템인지 체크한다. 보통 고유한 id를 기준으로 비교한다.
- areContentsTheSame() : 두 아이템이 동일한 내용물을 가지고 있는지 체크한다. 이 메서드는 areItemsTheSame()이 true일 때 호출된다.
구현한 DiffUtil은 Adapter 클래스에서 다음과 같이 사용해주면 된다.
( ... 은 생략된 코드이다.)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
public class TodoAdapter extends ListAdapter<Todo, TodoAdapter.ItemViewHolder> {
public TodoAdapter() {
super(DIFF_CALLBACK);
}
@NonNull
@Override
public ItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
...
}
@Override
public void onBindViewHolder(@NonNull TodoAdapter.ItemViewHolder holder, int position) {
...
}
class ItemViewHolder extends RecyclerView.ViewHolder {
...
}
public static DiffUtil.ItemCallback<Todo> DIFF_CALLBACK = new DiffUtil.ItemCallback<Todo>() {
...
};
}
|
cs |
아래에서 구현한 DiffUtil.ItemCallback을 생성자에서 부모클래스 생성자의 인자로 넘겨주면 부모클래스 코드에서 AsyncListDiffer 객체를 자동으로 생산해준다.
AsyncListDiffer는 DiffUtil을 통해서 두 리스트의 차이를 계산하는 과정을 백그라운드에서 이행하도록 도와주는 헬퍼 클래스이다.
3. ListAdapter는 무엇인고?
위 내용에서 이어지는 내용이다. AsyncListDiffer 클래스를 쉽게 사용하기 위해 ListAdapter를 활용할 수 있다. ListAdapter의 생성자에서 DiffUtil.ItemCallback을 인자로 넘겨주면서 사용한다.
백그라운드 스레드에서 리스트의 변화를 계산하는 RecyclerView.Adapter를 상속받는 클래스이다. ListAdapter는 AsyncListDiffer의 wrapper 클래스이다.
이 클래스에서 사용할 수 있는 메서드는 다음과 같다.
- getCurrentList() : 현재 리스트를 반환한다.
- onCurrentListChanged() : 리스트가 업데이트 되었을 때 실행할 콜백을 지정할 수 있다.
- submitList(List<T>) : 리스트 데이터를 교체할 때 사용한다.
참고자료
'Programming > 안드로이드(Android)' 카테고리의 다른 글
[Android] 안드로이드 4대 컴포넌트 - 초간단 (0) | 2020.12.20 |
---|---|
[Android] 안드로이드 플랫폼 아키텍처 (0) | 2020.12.20 |
[Android] 안드로이드 앱 개발 특징 (0) | 2020.12.20 |
Room 라이브러리 적용하기! (0) | 2020.12.03 |
[Android] 데이터 바인딩이 효과적인 이유 (0) | 2020.11.15 |