RecyclerView의 Adapter와 ViewHolder
MVVM에서는, View를 가지고 있는 ViewHolder나, ViewHolder에 데이터를 넣어주는 Adapter나 둘 다 (V)로 분류한다.
ViewHolder
Adapter
Adapter의 역할은
1. 실제 Data를 들고 있으면서,
2. 이 Data를 ViewHolder안에 있는 View에 할당(bind)해 준다.
3. List에 표시될 Item이 어떤 View를 사용할건지도 여기서 결정한다. (예를 들어 only_image_item.xml을 사용할건지, image_with_text_item.xml을 사용할건지 같은 것.)
Adapter는 Data를 들고 있어야 하니 Data의 성격도 가지고 있으면서, 동시에 이 데이터를 View로 연결해줘야 하니 View의 성격도 가지고 있다고 볼 수 있다.
** 인터페이스를 이용해서 AdapterDataModel과 AdapterDataView로 분리하기도 하는데 이렇게까지는 잘 안하고, 그냥 저렇다고 알고만 있으면 될 듯.
```kt
class RepoSelectAdapter : RecyclerView.Adapter<RepoViewHolder>() {
var items = mutableListOf<RepoItem>()
...
override fun onBindViewHolder(viewHolder: RepoViewHolder, idx: Int) {
viewHolder.name.text = items[idx].full_name
}
...
```
data binding을 쓰면 이렇게 된다. (MVVM아님.)
```kt
class RepoSelectAdapter : RecyclerView.Adapter<RepoViewHolder>() {
...
override fun onBindViewHolder(repoViewHolder: RepoViewHolder, position: Int) {
repoViewHolder.binding.repo = items.get(position)
}
inner class RepoViewHolder(view: View): RecyclerView.ViewHolder(view) {
val binding: RepoItemBinding = DataBindingUtil.bind(view)!!
}
```
RecyclerView의 MVVM
두 개를 고려해야 한다.
1. RecyclerView가 가지고 있는 ItemList에 뭔가가 추가되거나 삭제되어 리스트 자체에 변화가 생긴 경우.
2. 리스트의 원소인 한 Item 내에서 텍스트가 변경된다던가 하는, Item 내에서 변화가 생긴 경우.
그래서 결국 ViewModel은 2개 필요함.
onClick이 좀 까다로운데, repo_item.xml에서 () -> vm.onClick() 으로 지정할 수 있으려면 RepoItemViewModel에 onClick()함수가 있어야 한다.
그런데 onClick의 동작이 이런 저런 context를 다뤄야 하는 등 뷰와 관련된 코드다. 그래서 코드 본체는 RepoViewHolder.onItemClick()에 두고, 이 함수를 주고 받을 수 있는 Interface를 하나 정의한 다음 ViewModel을 선언하면서 이 함수를 넘기고 ViewModel의 onClick() 함수 내에서 listener.onItemClick()을 불러주도록 구성했다.
RecyclerView의 무한 스크롤 (load more) 최하단 감지하기
https://medium.com/@ydh0256/android-recyclerview-최상단과 최하단 이벤트 감지하기
``kt RecyclerView.OnScrollListener()``를 override해서 지정한다.
참고 ) 이 클래스는 메서드가 2개이므로 data binding으로(android:onScroll) 지정하는 것이 불가능하다. 직접 코드에서 붙여주어야 한다.
근데 안드로이드 jet pack에 포함된 paging library를 쓰면 무한 스크롤을 자동으로 처리해준다...
여러 모로 장점이 많으니 고려해볼 것.
ViewModel의 Observable 변수에 대한 참조를 Adapter를 만들면서 전달해도 괜찮은가?
방법은 총 3가지 정도 되는데...
- MainActivity에서 Adapter를 생성하면서 생성자로 ViewModel.items을 넘겨 레퍼런스를 갖게 하는 방법.
- @BindingAdapter를 써서 인자로 넘어온 item을, adpater.items = items으로 할당.
- @BindingAdapter를 써서 인자로 넘어온 item을, adpater.updateItems(items)으로 addAll.
'Java Stack > Android' 카테고리의 다른 글
MVVM과 Android DataBinding (3) | 2019.07.04 |
---|---|
Chrome Custom Tabs (0) | 2018.12.30 |
[Android] HTTP 요청 (Retrofit / OkHttp) (0) | 2018.12.26 |
Android Widget 제작 참고 자료 및 주의 사항 (0) | 2018.12.23 |
액티비티 : Activity life cycle, 백스택, singleTop (0) | 2018.05.20 |