일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- DevelopmentRegion
- 스크롤 탭
- convert base64
- SwiftUI
- UIPresentationController
- 기존 앱
- 상단 탭바
- scrolling tab
- 개발자 면접
- Swift Package Manager
- ViewBuilder
- transformation.map
- base64 변환
- url 추적
- GeometryReader
- List
- ios
- development language
- pod install
- swift #swift keychain #keychain 사용법
- Android
- DataBinding
- Side Menu
- url 관찰
- Tuist
- detect url
- UIViewControllerTransitioningDelegate
- oberve url
- notifychanged
- swift
- Today
- Total
버그 잡이
(AAC 응용) LiveData+Room+RecyclerView #DiffUtil 본문
(AAC 응용) LiveData+Room+RecyclerView #DiffUtil
버그잡이 2020. 4. 15. 14:23기본 리사이클러뷰 만들기는 저번 글 참고
https://jinsangjin.tistory.com/24
LiveData + Room 적용시 Issue
1. LiveData로 감싸진 Room 데이터를 todolist.value처럼 그냥 사용하려면 NPE 발생
viewModel.todoList.let {
it.value?.let{
viewAdapter = TodoListAdapter(it)
todoRecyclerView.setHasFixedSize(true)
todoRecyclerView.adapter = viewAdapter
}
it.observe(this, Observer {
viewAdapter.notifyDataSetChanged()
})
}
// *todoList : LiveData<List<TodoData>>
위와 같이 liveData의 value값만 받아서 넣으려는데 자꾸 NPE 뜬다.
왜 그런지 알아보니 LiveData로 감싸진 room데이터는 observer 안에서만 받을 수 있단다.
roomDB는 메인스레드에서 접근할 수 없어서 그런 것이라고 한다.
https://stackoverflow.com/questions/44428389/livedata-getvalue-returns-null-with-room
(수정 후)
viewModel.todoList.observe(this, Observer {
val viewAdapter = TodoListAdapter(it)
binding.todoRecyclerView.adapter = viewAdapter
viewAdapter.notifyDataSetChanged()
})
2. 위와 같이 observer에서 데이터를 받을 경우 viewAdapter를 매번 최신화 해야하는 문제
-> Adapter에서 list 받는 것을 constructor가 아닌 setter로 바꿔준다.
*TodoListAdapter
- adapter에서 constructor로 받는 변수를 지우고 다음과 같은 setter를 생성한다.
var list = listOf<TodoData>()
set(value) {
field = value
notifyDataSetChanged()
}
*MainActivity
val viewAdapter = TodoListAdapter()
binding.todoRecyclerView.adapter = viewAdapter
viewModel.todoList.observe(this, Observer {
viewAdapter.list = it
viewAdapter.notifyDataSetChanged()
})
DiffUtil의 활용
- notifyDataSetChanged는 리스트를 전부 최신화 하기 때문에 expensive한 작업이다.
- 이런 경우 DiffUtil을 사용하면 보다 효율적으로 데이터를 최신화할 수 있다.
(기존 데이터와 새로운 데이터를 비교해서 달라진 부분만 수정하는 그런 알고리즘이 담겨 있다고 한다.)
* DiffUtil 은 DB를 바탕으로 계산하기 때문에 계산 대상이 Room data class가 아니라 그냥 data class라면 계산이 적용되지 않는다.
1. DiffCallback 클래스 생성
*areItemTheSame은 말그대로 item이 추가되거나 삭제된 것이 있는지 확인
*areContentsTheSame은 itemId는 같지만 그 세부사항이 변경된 것이 있는지 확인. 특정 항목의 변화만 확인하고 싶으면 커스텀 해서 작성할 수 있다.
이 두가지 필터로 걸린 항목들을 최신화 하는 것이다.
class TodoListDiffCallback : DiffUtil.ItemCallback<TodoData>(){
override fun areItemsTheSame(oldItem: TodoData, newItem: TodoData): Boolean {
return oldItem.todoId == newItem.todoId
}
override fun areContentsTheSame(oldItem: TodoData, newItem: TodoData): Boolean {
return oldItem == newItem
}
}
2. Adapter 상속을 기존 recyclerView에서 listAdapter로 변경
- ListAdapter를 아래와 같이 상속 받는다.
class TodoListAdapter(): ListAdapter<TodoData, TodoListViewHolder>(TodoListDiffCallback()){
// var list = listOf<TodoData>()
// set(value) {
// field = value
// notifyDataSetChanged()
// }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TodoListViewHolder {
val todoItem = LayoutInflater.from(parent.context)
.inflate(R.layout.item_todo, parent, false)
return TodoListViewHolder(todoItem)
}
override fun onBindViewHolder(holder: TodoListViewHolder, position: Int) {
holder.containerView.todoContent.text = getItem(position).todoContent
}
//override fun getItemCount(): Int = list.size ?: 0
}
- 그 결과 setter, getItemCount는 필요가 없어진다.(ListAdapter에서 관련 기능을 제공)
*MainActivity.kt
val viewAdapter = TodoListAdapter()
binding.todoRecyclerView.adapter = view
viewModel.todoList.observe(this, Observer {
viewAdapter.submitList(it) //기존 viewAdapter.list = it 에서 다음과 같이 수정
})
'모던 안드로이드 > Udacity Android with kotlin' 카테고리의 다른 글
Retrofit+liveData+moshi 로 네트워크 통신하기 (0) | 2020.04.19 |
---|---|
(ViewModel+LiveData)Bottom Navigation 수직/수평 전환시 fragment 초기화 문제 해결 #configuration change (0) | 2020.04.16 |
(AAC 응용)ViewModel+LiveData+Room으로 ToDoList 앱 만들기 (0) | 2020.04.14 |
[Udacity android with kotlin] 6. Room #ViewModel+LiveData+Room (0) | 2020.04.14 |
[Udacity Android with Kotlin]2. Layout #BindingView #Constraint (0) | 2020.04.09 |