이 Codelab은 Android Kotlin 기초 과정의 일부입니다. Codelab을 순서대로 진행하면 이 과정의 학습 효과를 극대화할 수 있습니다. 모든 과정 Codelab은 Android Kotlin 기본사항 Codelab 방문 페이지에 나열되어 있습니다.
소개
이전 Codelab에서는 RecyclerView
에 수면의 질에 관한 데이터를 표시하도록 TrackMySleepQuality 앱을 업데이트했습니다. 첫 번째 RecyclerView
를 빌드할 때 배운 기술은 너무 크지 않은 간단한 목록을 표시하는 대부분의 RecyclerViews
에 충분합니다. 하지만 대규모 목록에서 RecyclerView
를 더 효율적으로 만들고 복잡한 목록과 그리드에서 코드를 더 쉽게 유지 관리하고 확장할 수 있는 여러 기법이 있습니다.
이 Codelab에서는 이전 Codelab의 수면 추적기 앱을 기반으로 빌드합니다. 수면 데이터 목록을 업데이트하는 더 효과적인 방법을 배우고 RecyclerView
와 함께 데이터 결합을 사용하는 방법을 알아봅니다. (이전 Codelab의 앱이 없는 경우 이 Codelab의 시작 코드를 다운로드하면 됩니다.)
기본 요건
- 활동, 프래그먼트, 뷰를 사용하여 기본 사용자 인터페이스를 빌드합니다.
- 프래그먼트 간 탐색 및
safeArgs
을 사용하여 프래그먼트 간 데이터 전달 - 모델, 모델 팩토리, 변환,
LiveData
및 관찰자를 확인합니다. Room
데이터베이스를 만들고, DAO를 만들고, 항목을 정의하는 방법- 데이터베이스 및 기타 장기 실행 작업에 코루틴을 사용하는 방법
Adapter
,ViewHolder
, 항목 레이아웃으로 기본RecyclerView
를 구현하는 방법
학습할 내용
DiffUtil
를 사용하여RecyclerView
에 표시된 목록을 효율적으로 업데이트하는 방법RecyclerView
와 함께 데이터 결합을 사용하는 방법- 결합 어댑터를 사용하여 데이터를 변환하는 방법
실습할 내용
- 이 시리즈의 이전 Codelab에서 TrackMySleepQuality 앱을 기반으로 빌드합니다.
DiffUtil
을 사용하여 목록을 효율적으로 업데이트하도록SleepNightAdapter
을 업데이트합니다.- 결합 어댑터를 사용하여 데이터를 변환하여
RecyclerView
에 데이터 결합을 구현합니다.
수면 추적기 앱에는 아래 그림과 같이 프래그먼트로 표시되는 두 개의 화면이 있습니다.
왼쪽에 표시된 첫 번째 화면에는 추적을 시작하고 중지하는 버튼이 있습니다. 화면에는 사용자의 수면 데이터가 일부 표시됩니다. 지우기 버튼은 앱이 사용자를 위해 수집한 모든 데이터를 완전히 삭제합니다. 오른쪽에 표시된 두 번째 화면은 수면의 질 평가를 선택하는 화면입니다.
이 앱은 UI 컨트롤러(ViewModel
및 LiveData
)와 Room
데이터베이스를 사용하여 수면 데이터를 유지하도록 설계되었습니다.
수면 데이터가 RecyclerView
에 표시됩니다. 이 Codelab에서는 RecyclerView
의 DiffUtil
및 데이터 바인딩 부분을 빌드합니다. 이 Codelab을 마치면 앱은 똑같아 보이지만 더 효율적이고 확장 및 유지 관리가 더 쉬워집니다.
이전 Codelab의 SleepTracker 앱을 계속 사용하거나 GitHub에서 RecyclerViewDiffUtilDataBinding-Starter 앱을 다운로드할 수 있습니다.
- 필요한 경우 GitHub에서 RecyclerViewDiffUtilDataBinding-Starter 앱을 다운로드하고 Android 스튜디오에서 프로젝트를 엽니다.
- 앱을 실행합니다.
SleepNightAdapter.kt
파일을 엽니다.- 코드를 검사하여 앱의 구조를 숙지합니다. 어댑터 패턴과 함께
RecyclerView
를 사용하여 사용자에게 수면 데이터를 표시하는 방법을 요약한 아래 다이어그램을 참고하세요.
- 사용자 입력에서 앱은
SleepNight
객체 목록을 만듭니다. 각SleepNight
객체는 단일 수면 시간, 수면 시간, 수면의 질을 나타냅니다. SleepNightAdapter
는SleepNight
객체 목록을RecyclerView
에서 사용하고 표시할 수 있는 형식으로 조정합니다.SleepNightAdapter
어댑터는 리사이클러 뷰가 데이터를 표시할 수 있도록 뷰, 데이터, 메타 정보가 포함된ViewHolders
를 생성합니다.RecyclerView
는SleepNightAdapter
를 사용하여 표시할 항목 수 (getItemCount()
)를 결정합니다.RecyclerView
는onCreateViewHolder()
및onBindViewHolder()
를 사용하여 표시할 데이터에 바인딩된 뷰 홀더를 가져옵니다.
notifyDataSetChanged() 메서드가 비효율적임
목록의 항목이 변경되어 업데이트해야 함을 RecyclerView
에 알리기 위해 현재 코드는 아래와 같이 SleepNightAdapter
에서 notifyDataSetChanged()
를 호출합니다.
var data = listOf<SleepNight>()
set(value) {
field = value
notifyDataSetChanged()
}
하지만 notifyDataSetChanged()
는 RecyclerView
에게 전체 목록이 유효하지 않을 수 있다고 알려줍니다. 따라서 RecyclerView
는 화면에 표시되지 않는 항목을 포함하여 목록의 모든 항목을 다시 바인딩하고 다시 그립니다. 이는 불필요한 작업이 많습니다. 크거나 복잡한 목록의 경우 이 프로세스에 시간이 오래 걸려 사용자가 목록을 스크롤할 때 디스플레이가 깜박이거나 끊길 수 있습니다.
이 문제를 해결하려면 RecyclerView
에 변경된 내용을 정확하게 알려주면 됩니다. 그러면 RecyclerView
가 화면에서 변경된 뷰만 업데이트할 수 있습니다.
RecyclerView
에는 단일 요소를 업데이트하기 위한 다양한 API가 있습니다. notifyItemChanged()
를 사용하여 RecyclerView
에 항목이 변경되었음을 알릴 수 있으며, 추가, 삭제 또는 이동된 항목에 유사한 함수를 사용할 수 있습니다. 모든 작업을 수동으로 할 수도 있지만 이 작업은 간단하지 않으며 상당한 코드가 필요할 수 있습니다.
다행히 더 나은 방법이 있습니다.
DiffUtil은 효율적이며 어려운 작업을 대신 처리합니다.
RecyclerView
에는 두 목록 간의 차이를 계산하는 데 사용되는 DiffUtil
이라는 클래스가 있습니다. DiffUtil
는 이전 목록과 새 목록을 가져와서 다른 점을 파악합니다. 추가, 삭제 또는 변경된 항목을 찾습니다. 그런 다음 Eugene W. Myers's difference algorithm을 사용하여 이전 목록에서 새 목록을 생성하기 위해 변경해야 하는 최소 횟수를 파악합니다.
DiffUtil
가 변경된 항목을 파악하면 RecyclerView
는 이 정보를 사용하여 변경, 추가, 삭제 또는 이동된 항목만 업데이트할 수 있으므로 전체 목록을 다시 실행하는 것보다 훨씬 효율적입니다.
이 작업에서는 DiffUtil
를 사용하여 데이터 변경사항에 맞게 RecyclerView
를 최적화하도록 SleepNightAdapter
를 업그레이드합니다.
1단계: SleepNightDiffCallback 구현
DiffUtil
클래스의 기능을 사용하려면 DiffUtil.ItemCallback
를 확장하세요.
SleepNightAdapter.kt
를 엽니다.SleepNightAdapter
의 전체 클래스 정의 아래에서DiffUtil.ItemCallback
를 확장하는SleepNightDiffCallback
이라는 새 최상위 클래스를 만듭니다.SleepNight
를 일반 매개변수로 전달합니다.
class SleepNightDiffCallback : DiffUtil.ItemCallback<SleepNight>() {
}
SleepNightDiffCallback
클래스 이름에 커서를 놓습니다.Alt+Enter
(Mac의 경우Option+Enter
)을 누르고 Implement Members를 선택합니다.- 열린 대화상자에서 Shift 키를 누른 채 왼쪽 클릭하여
areItemsTheSame()
및areContentsTheSame()
메서드를 선택한 후 OK를 클릭합니다.
그러면 아래와 같이 두 메서드의 스텁이SleepNightDiffCallback
내부에 생성됩니다.DiffUtil
은 이러한 두 가지 메서드를 사용하여 목록과 항목이 어떻게 변경되었는지 파악합니다.
override fun areItemsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun areContentsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
areItemsTheSame()
내에서TODO
을 전달된 두SleepNight
항목(oldItem
및newItem
)이 동일한지 테스트하는 코드로 바꿉니다. 상품의nightId
이 동일하면 동일한 상품이므로true
을 반환합니다. 그렇지 않으면false
을 반환합니다.DiffUtil
은 이 테스트를 사용하여 항목이 추가, 삭제 또는 이동되었는지 확인합니다.
override fun areItemsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
return oldItem.nightId == newItem.nightId
}
areContentsTheSame()
내에서oldItem
와newItem
에 동일한 데이터가 포함되어 있는지, 즉 동일한지 확인합니다.SleepNight
는 데이터 클래스이므로 이 동등성 검사는 모든 필드를 확인합니다.Data
클래스는equals
및 몇 가지 다른 메서드를 자동으로 정의합니다.oldItem
과newItem
사이에 차이가 있으면 이 코드는DiffUtil
에 항목이 업데이트되었음을 알립니다.
override fun areContentsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
return oldItem == newItem
}
RecyclerView
를 사용하여 변경되는 목록을 표시하는 것이 일반적인 패턴입니다. RecyclerView
는 목록으로 지원되는 RecyclerView
어댑터를 빌드하는 데 도움이 되는 어댑터 클래스 ListAdapter
를 제공합니다.
ListAdapter
는 목록을 추적하고 목록이 업데이트되면 어댑터에 알립니다.
1단계: 어댑터를 변경하여 ListAdapter 확장
SleepNightAdapter.kt
파일에서ListAdapter
를 확장하도록SleepNightAdapter
의 클래스 서명을 변경합니다.- 메시지가 표시되면
androidx.recyclerview.widget.ListAdapter
를 가져옵니다. SleepNightAdapter.ViewHolder
앞에ListAdapter
에SleepNight
를 첫 번째 인수로 추가합니다.- 생성자에
SleepNightDiffCallback()
을 매개변수로 추가합니다.ListAdapter
는 이를 사용하여 목록에서 변경된 내용을 파악합니다. 완성된SleepNightAdapter
클래스 서명은 아래와 같이 표시됩니다.
class SleepNightAdapter : ListAdapter<SleepNight, SleepNightAdapter.ViewHolder>(SleepNightDiffCallback()) {
SleepNightAdapter
클래스 내에서 setter를 포함한data
필드를 삭제합니다.ListAdapter
에서 목록을 추적하므로 더 이상 필요하지 않습니다.ListAdapter
이 이 메서드를 구현하므로getItemCount()
의 재정의를 삭제합니다.onBindViewHolder()
의 오류를 없애려면item
변수를 변경하세요.data
를 사용하여item
를 가져오는 대신ListAdapter
에서 제공하는getItem(position)
메서드를 호출합니다.
val item = getItem(position)
2단계: submitList()를 사용하여 목록을 업데이트된 상태로 유지
변경된 목록을 사용할 수 있을 때 코드가 ListAdapter
에 알려야 합니다. ListAdapter
는 새 버전의 목록을 사용할 수 있음을 ListAdapter
에 알리는 submitList()
이라는 메서드를 제공합니다. 이 메서드가 호출되면 ListAdapter
는 새 목록과 이전 목록을 비교하여 추가, 삭제, 이동 또는 변경된 항목을 감지합니다. 그러면 ListAdapter
이 RecyclerView
에 표시된 항목을 업데이트합니다.
SleepTrackerFragment.kt
를 엽니다.onCreateView()
에서sleepTrackerViewModel
의 관찰자에서 삭제한data
변수가 참조되는 오류를 찾습니다.adapter.data = it
을adapter.submitList(it)
호출로 바꿉니다. 업데이트된 코드는 아래와 같습니다.
sleepTrackerViewModel.nights.observe(viewLifecycleOwner, Observer {
it?.let {
adapter.submitList(it)
}
})
- 앱을 실행합니다. 목록이 작으면 눈에 띄지 않을 수 있지만 더 빠르게 실행됩니다.
이 작업에서는 이전 Codelab과 동일한 기법을 사용하여 데이터 바인딩을 설정하고 findViewById()
호출을 삭제합니다.
1단계: 레이아웃 파일에 데이터 결합 추가
- 텍스트 탭에서
list_item_sleep_night.xml
레이아웃 파일을 엽니다. ConstraintLayout
태그에 커서를 놓고Alt+Enter
(Mac의 경우Option+Enter
)를 누릅니다. 의도 메뉴('빠른 수정' 메뉴)가 열립니다.- 데이터 결합 레이아웃으로 변환을 선택합니다. 이렇게 하면 레이아웃이
<layout>
로 래핑되고 내부에<data>
태그가 추가됩니다. - 필요한 경우 상단으로 스크롤하고
<data>
태그 내에서sleep
이라는 변수를 선언합니다. type
을SleepNight
,com.example.android.trackmysleepquality.database.SleepNight
의 정규화된 이름으로 만듭니다. 완성된<data>
태그는 아래와 같이 표시됩니다.
<data>
<variable
name="sleep"
type="com.example.android.trackmysleepquality.database.SleepNight"/>
</data>
Binding
객체의 생성을 강제하려면 Build > Clean Project를 선택한 다음 Build > Rebuild Project를 선택합니다. (그래도 문제가 해결되지 않으면 File > Invalidate Caches / Restart를 선택하세요.)ListItemSleepNightBinding
바인딩 객체와 관련 코드가 프로젝트의 생성된 파일에 추가됩니다.
2단계: 데이터 결합을 사용하여 항목 레이아웃 확장
SleepNightAdapter.kt
를 엽니다.ViewHolder
클래스에서from()
메서드를 찾습니다.view
변수의 선언을 삭제합니다.
삭제할 코드:
val view = layoutInflater
.inflate(R.layout.list_item_sleep_night, parent, false)
view
변수가 있던 위치에ListItemSleepNightBinding
바인딩 객체를 인플레이션하는binding
이라는 새 변수를 정의합니다(아래 참고). 바인딩 객체를 필요한 대로 가져옵니다.
val binding =
ListItemSleepNightBinding.inflate(layoutInflater, parent, false)
- 함수 끝에서
view
를 반환하는 대신binding
를 반환합니다.
return ViewHolder(binding)
- 이 오류를 없애려면
binding
단어에 커서를 놓습니다.Alt+Enter
(Mac의 경우Option+Enter
)를 눌러 의도 메뉴를 엽니다.
- 클래스 'ViewHolder'의 기본 생성자의 'itemView' 유형을 'ListItemSleepNightBinding'으로 변경을 선택합니다. 이렇게 하면
ViewHolder
클래스의 매개변수 유형이 업데이트됩니다.
- 위로 스크롤하여
ViewHolder
의 클래스 정의를 확인하여 서명의 변경사항을 확인합니다.from()
메서드에서itemView
을binding
로 변경했기 때문에itemView
에 오류가 표시됩니다.ViewHolder
클래스 정의에서itemView
이 나타나는 위치 중 하나를 마우스 오른쪽 버튼으로 클릭하고 리팩터링 > 이름 바꾸기를 선택합니다. 이름을binding
로 변경합니다. - 생성자 매개변수
binding
에val
을 접두사로 추가하여 속성으로 만듭니다. - 부모 클래스
RecyclerView.ViewHolder
호출에서 매개변수를binding
에서binding.root
로 변경합니다.View
를 전달해야 하며binding.root
은 항목 레이아웃의 루트ConstraintLayout
입니다. - 완성된 클래스 선언은 아래 코드와 같이 표시됩니다.
class ViewHolder private constructor(val binding: ListItemSleepNightBinding) : RecyclerView.ViewHolder(binding.root){
findViewById()
호출에 관한 오류도 표시되므로 다음으로 이 오류를 수정합니다.
3단계: findViewById() 대체
이제 findViewById()
대신 binding
객체를 사용하도록 sleepLength
, quality
, qualityImage
속성을 업데이트할 수 있습니다.
- 아래와 같이
binding
객체의 뷰를 사용하도록sleepLength
,qualityString
,qualityImage
의 초기화를 변경합니다. 이후에는 코드에 오류가 더 이상 표시되지 않습니다.
val sleepLength: TextView = binding.sleepLength
val quality: TextView = binding.qualityString
val qualityImage: ImageView = binding.qualityImage
바인딩 객체가 있으면 sleepLength
, quality
, qualityImage
속성을 더 이상 정의하지 않아도 됩니다. DataBinding
는 조회를 캐시하므로 이러한 속성을 선언할 필요가 없습니다.
sleepLength
,quality
,qualityImage
속성 이름을 마우스 오른쪽 버튼으로 클릭합니다. 리팩터링 > 인라인을 선택하거나Control+Command+N
(Mac의 경우Option+Command+N
)를 누릅니다.- 앱을 실행합니다. 오류가 있는 경우 프로젝트를 정리하고 다시 빌드해야 할 수 있습니다.
이 작업에서는 결합 어댑터와 함께 데이터 결합을 사용하여 뷰에 데이터를 설정하도록 앱을 업그레이드합니다.
이전 Codelab에서는 Transformations
클래스를 사용하여 LiveData
를 가져오고 텍스트 뷰에 표시할 서식이 지정된 문자열을 생성했습니다. 하지만 다른 유형이나 복잡한 유형을 바인딩해야 하는 경우 데이터 바인딩이 이러한 유형을 사용할 수 있도록 바인딩 어댑터를 제공할 수 있습니다. 결합 어댑터는 데이터를 가져와 데이터 결합이 텍스트나 이미지와 같은 뷰를 결합하는 데 사용할 수 있는 형식으로 조정하는 어댑터입니다.
품질 이미지용 바인딩 어댑터 하나와 각 텍스트 필드용 바인딩 어댑터 하나씩 총 세 개의 바인딩 어댑터를 구현합니다. 요약하자면 결합 어댑터를 선언하려면 항목과 뷰를 사용하는 메서드를 정의하고 @BindingAdapter
로 주석을 답니다. 메서드의 본문에서 변환을 구현합니다. Kotlin에서는 데이터를 수신하는 뷰 클래스에서 확장 함수로 바인딩 어댑터를 작성할 수 있습니다.
1단계: 바인딩 어댑터 만들기
이 단계에서는 여러 클래스를 가져와야 하며 개별적으로 호출되지 않습니다.
SleepNightAdapater.kt
를 엽니다.ViewHolder
클래스 내에서bind()
메서드를 찾아 이 메서드의 기능을 다시 확인합니다.binding.sleepLength
,binding.quality
,binding.qualityImage
값을 계산하는 코드를 가져와 어댑터 내에서 대신 사용합니다. (지금은 코드를 그대로 두세요. 나중에 이동합니다.)sleeptracker
패키지에서BindingUtils.kt
이라는 파일을 만들어 엽니다.TextView
에서setSleepDurationFormatted
이라는 확장 함수를 선언하고SleepNight
를 전달합니다. 이 함수는 수면 시간을 계산하고 형식을 지정하는 어댑터가 됩니다.
fun TextView.setSleepDurationFormatted(item: SleepNight) {}
setSleepDurationFormatted
본문에서ViewHolder.bind()
에서 한 것처럼 데이터를 뷰에 바인딩합니다.convertDurationToFormatted()
를 호출한 다음TextView
의text
을 형식이 지정된 텍스트로 설정합니다. (TextView
의 확장 함수이므로text
속성에 직접 액세스할 수 있습니다.)
text = convertDurationToFormatted(item.startTimeMilli, item.endTimeMilli, context.resources)
- 이 결합 어댑터에 관해 데이터 결합에 알리려면 함수에
@BindingAdapter
주석을 추가합니다. - 이 함수는
sleepDurationFormatted
속성의 어댑터이므로sleepDurationFormatted
를@BindingAdapter
에 인수로 전달합니다.
@BindingAdapter("sleepDurationFormatted")
- 두 번째 어댑터는
SleepNight
객체의 값을 기반으로 수면 효율을 설정합니다.TextView
에서setSleepQualityString()
라는 확장 함수를 만들고SleepNight
를 전달합니다. - 본문에서
ViewHolder.bind()
에서와 같이 데이터를 뷰에 바인딩합니다.convertNumericQualityToString
를 호출하고text
를 설정합니다. - 함수에
@BindingAdapter("sleepQualityString")
주석을 추가합니다.
@BindingAdapter("sleepQualityString")
fun TextView.setSleepQualityString(item: SleepNight) {
text = convertNumericQualityToString(item.sleepQuality, context.resources)
}
- 세 번째 결합 어댑터는 이미지 뷰에 이미지를 설정합니다.
ImageView
에서 확장 함수를 만들고setSleepImage
를 호출하고ViewHolder.bind()
의 코드를 사용합니다(아래 참고).
@BindingAdapter("sleepImage")
fun ImageView.setSleepImage(item: SleepNight) {
setImageResource(when (item.sleepQuality) {
0 -> R.drawable.ic_sleep_0
1 -> R.drawable.ic_sleep_1
2 -> R.drawable.ic_sleep_2
3 -> R.drawable.ic_sleep_3
4 -> R.drawable.ic_sleep_4
5 -> R.drawable.ic_sleep_5
else -> R.drawable.ic_sleep_active
})
}
2단계: SleepNightAdapter 업데이트
SleepNightAdapter.kt
를 엽니다.- 이제 데이터 바인딩과 새 어댑터를 사용하여 이 작업을 수행할 수 있으므로
bind()
메서드의 모든 항목을 삭제합니다.
fun bind(item: SleepNight) {
}
bind()
내에서item
에 절전을 할당합니다. 바인딩 객체에 새SleepNight
에 관해 알려야 하기 때문입니다.
binding.sleep = item
- 이 줄 아래에
binding.executePendingBindings()
를 추가합니다. 이 호출은 데이터 바인딩이 대기 중인 바인딩을 즉시 실행하도록 요청하는 최적화입니다.RecyclerView
에서 바인딩 어댑터를 사용할 때는 항상executePendingBindings()
를 호출하는 것이 좋습니다. 뷰의 크기 조정을 약간 빠르게 할 수 있기 때문입니다.
binding.executePendingBindings()
3단계: XML 레이아웃에 바인딩 추가
list_item_sleep_night.xml
를 엽니다.ImageView
에서 이미지를 설정하는 결합 어댑터와 이름이 동일한app
속성을 추가합니다. 아래와 같이sleep
변수를 전달합니다.
이 속성은 어댑터를 통해 뷰와 바인딩 객체 간 연결을 만듭니다.sleepImage
가 참조될 때마다 어댑터는SleepNight
의 데이터를 적응시킵니다.
app:sleepImage="@{sleep}"
sleep_length
및quality_string
텍스트 뷰에도 동일한 작업을 실행합니다.sleepDurationFormatted
또는sleepQualityString
가 참조될 때마다 어댑터는SleepNight
의 데이터를 적응시킵니다.
app:sleepDurationFormatted="@{sleep}"
app:sleepQualityString="@{sleep}"
- 앱을 실행합니다. 이전과 정확히 동일하게 작동합니다. 바인딩 어댑터는 데이터가 변경될 때 뷰의 형식을 지정하고 업데이트하는 모든 작업을 처리하여
ViewHolder
를 간소화하고 이전보다 훨씬 나은 코드 구조를 제공합니다.
마지막 몇 가지 운동에서 동일한 목록을 표시했습니다. 이는 Adapter
인터페이스를 사용하면 다양한 방식으로 코드를 설계할 수 있음을 보여주기 위한 것입니다. 코드가 복잡할수록 아키텍처를 잘 설계하는 것이 중요해집니다. 프로덕션 앱에서는 이러한 패턴과 기타 패턴이 RecyclerView
와 함께 사용됩니다. 이러한 패턴은 모두 작동하며 각각 장점이 있습니다. 어떤 것을 선택할지는 빌드하는 항목에 따라 다릅니다.
축하합니다. 이제 Android에서 RecyclerView
를 마스터하기 위한 과정을 잘 밟아가고 계십니다.
Android 스튜디오 프로젝트: RecyclerViewDiffUtilDataBinding
DiffUtil
:
RecyclerView
에는 두 목록 간의 차이를 계산하는 데 사용되는DiffUtil
이라는 클래스가 있습니다.DiffUtil
에는 두 목록 간의 차이를 파악하기 위해 확장하는ItemCallBack
이라는 클래스가 있습니다.ItemCallback
클래스에서areItemsTheSame()
메서드와areContentsTheSame()
메서드를 재정의해야 합니다.
ListAdapter
:
- 목록 관리를 무료로 받으려면
RecyclerView.Adapter
대신ListAdapter
클래스를 사용하면 됩니다. 하지만ListAdapter
를 사용하는 경우 다른 레이아웃의 어댑터를 직접 작성해야 하므로 이 Codelab에서는 방법을 보여줍니다. - Android 스튜디오에서 의도 메뉴를 열려면 코드 항목에 커서를 놓고
Alt+Enter
(Mac의 경우Option+Enter
)를 누릅니다. 이 메뉴는 특히 코드를 리팩터링하고 메서드를 구현하기 위한 스텁을 만드는 데 유용합니다. 메뉴는 상황에 따라 달라지므로 올바른 메뉴를 표시하려면 커서를 정확하게 배치해야 합니다.
데이터 결합:
- 항목 레이아웃에서 데이터 결합을 사용하여 데이터를 뷰에 결합합니다.
결합 어댑터:
- 이전에는
Transformations
를 사용하여 데이터에서 문자열을 만들었습니다. 다양하거나 복잡한 유형의 데이터를 바인딩해야 하는 경우 데이터 바인딩이 이를 사용할 수 있도록 바인딩 어댑터를 제공하세요. - 결합 어댑터를 선언하려면 항목과 뷰를 사용하는 메서드를 정의하고 메서드에
@BindingAdapter
주석을 추가합니다. Kotlin에서는View
의 확장 함수로 바인딩 어댑터를 작성할 수 있습니다. 어댑터가 적응하는 속성의 이름을 전달합니다. 예를 들면 다음과 같습니다.
@BindingAdapter("sleepDurationFormatted")
- XML 레이아웃에서 바인딩 어댑터와 이름이 같은
app
속성을 설정합니다. 데이터가 포함된 변수를 전달합니다. 예를 들면 다음과 같습니다.
.app:sleepDurationFormatted="@{sleep}"
Udacity 과정:
Android 개발자 문서:
- RecyclerView로 목록 만들기
RecyclerView
DiffUtil
- 데이터 결합 라이브러리
- 결합 어댑터
notifyDataSetChanged()
Transformations
기타 자료:
이 섹션에는 강사가 진행하는 과정의 일부로 이 Codelab을 진행하는 학생에게 출제할 수 있는 과제가 나열되어 있습니다. 다음 작업은 강사가 결정합니다.
- 필요한 경우 과제를 할당합니다.
- 과제 제출 방법을 학생에게 알립니다.
- 과제를 채점합니다.
강사는 이러한 추천을 원하는 만큼 사용할 수 있으며 적절하다고 생각되는 다른 과제를 출제해도 됩니다.
이 Codelab을 직접 진행하는 경우 이러한 과제를 자유롭게 사용하여 배운 내용을 테스트해 보세요.
질문에 답하세요
질문 1
다음 중 DiffUtil
을 사용하는 데 필요한 것은 무엇인가요? 해당하는 항목을 모두 선택해 주세요.
▢ ItemCallBack
클래스를 확장합니다.
▢ areItemsTheSame()
재정의
▢ areContentsTheSame()
재정의
▢ 데이터 결합을 사용하여 항목 간의 차이점을 추적합니다.
질문 2
결합 어댑터에 관한 다음 설명 중 참인 것은 무엇인가요?
▢ 바인딩 어댑터는 @BindingAdapter
로 주석 처리된 함수입니다.
▢ 바인딩 어댑터를 사용하면 뷰 홀더로부터 데이터 형식을 분리할 수 있습니다.
▢ 결합 어댑터를 사용하려면 RecyclerViewAdapter
를 사용해야 합니다.
▢ 복잡한 데이터를 변환해야 하는 경우 결합 어댑터는 좋은 솔루션이 됩니다.
질문 3
언제 결합 어댑터 대신 Transformations
를 사용하는 것이 좋을까요? 해당하는 항목을 모두 선택해 주세요.
▢ 데이터가 간단합니다.
▢ 문자열의 형식을 지정하고 있습니다.
▢ 목록이 너무 깁니다.
▢ ViewHolder
에 뷰가 하나만 포함되어 있습니다.
다음 강의 시작: