Android Kotlin 기초 06.3: LiveData를 사용하여 버튼 상태 제어

이 Codelab은 Android Kotlin 기초 교육 과정의 일부입니다. Codelab을 순서대로 진행한다면 이 과정을 통해 최대한의 가치를 얻을 수 있을 것입니다. 모든 과정 Codelab은 Android Kotlin 기초 Codelab 방문 페이지에 나열되어 있습니다.

소개

이 Codelab에서는 ViewModel과 프래그먼트를 함께 사용하여 탐색을 구현하는 방법을 요약합니다. 목표는 ViewModel로 이동할 시기의 로직을 배치하는 것이지만 프래그먼트와 탐색 파일의 경로를 정의하는 것입니다. 이 목표를 달성하려면 뷰 모델, 프래그먼트, LiveData 및 관찰자를 사용합니다.

Codelab은 최소한의 코드로 버튼 상태를 추적하는 기발한 방법을 표시하여 마무리합니다. 그러면 각 버튼은 사용자가 버튼을 탭해야 하는 경우에만 사용 설정되고 클릭 가능합니다.

기본 요건

다음을 잘 알고 있어야 합니다.

  • 활동, 프래그먼트, 뷰를 사용하여 기본 사용자 인터페이스 (UI) 빌드
  • 프래그먼트 간 이동과 safeArgs을 사용하여 프래그먼트 간 데이터 전달
  • 모델 보기, 모델 팩토리, 변환, LiveData 및 그 관찰자를 봅니다.
  • Room 데이터베이스를 만들고 데이터 액세스 객체 (DAO)를 만들고 항목을 정의하는 방법
  • 데이터베이스 상호작용 및 기타 장기 실행 작업에 코루틴을 사용하는 방법

학습할 내용

  • 데이터베이스의 기존 수면 품질 레코드를 업데이트하는 방법
  • LiveData을 사용하여 버튼 상태를 추적하는 방법
  • 이벤트에 대한 응답으로 스낵바를 표시하는 방법

실습할 내용

  • TrackMySleepQuality 앱을 확장하여 품질 평점을 수집하고 데이터베이스에 평점을 추가하며 결과를 표시합니다.
  • LiveData를 사용하여 스낵바 표시를 트리거합니다.
  • LiveData를 사용하여 버튼을 사용 또는 사용 중지합니다.

이 Codelab에서는 TrackMySleepQuality 앱의 수면 품질 기록 및 최종 UI를 빌드합니다.

앱에는 아래 그림과 같이 프래그먼트로 표시된 두 개의 화면이 있습니다.

왼쪽에 표시된 첫 번째 화면에는 추적을 시작하고 중지하는 버튼이 있습니다. 화면에 사용자의 모든 수면 데이터가 표시됩니다. 지우기 버튼은 앱에서 사용자에 대해 수집한 모든 데이터를 완전히 삭제합니다.

오른쪽에 표시된 두 번째 화면은 수면의 질 등급을 선택하기 위한 것입니다. 앱에서 평점은 숫자로 표시됩니다. 앱이 개발 목적으로 얼굴 아이콘과 동등한 얼굴을 모두 표시합니다.

사용자 플로우는 다음과 같습니다.

  • 사용자가 앱을 열면 수면 추적 화면이 표시됩니다.
  • 사용자가 시작 버튼을 탭합니다. 그러면 시작 시간이 기록되고 표시됩니다. 시작 버튼이 사용 중지되고 중지 버튼이 사용 설정됩니다.
  • 사용자가 중지 버튼을 탭합니다. 이렇게 하면 종료 시간이 기록되고 수면의 질 화면이 열립니다.
  • 사용자가 수면의 질 아이콘을 선택합니다. 화면이 닫히고 추적 화면에 수면 종료 시간과 수면의 질이 표시됩니다. Stop 버튼이 사용 중지되고 Start 버튼이 사용 설정됩니다. 이제 앱을 하루 사용할 준비가 되었습니다.
  • 지우기 버튼은 데이터베이스에 데이터가 있을 때마다 사용 설정됩니다. 사용자가 지우기 버튼을 탭하면 거부 없이 모든 데이터가 삭제됩니다. 계속하시겠습니까?라는 메시지가 표시되지 않습니다.

이 앱은 전체 아키텍처의 컨텍스트에서 다음과 같이 단순화된 아키텍처를 사용합니다. 앱에서는 다음 구성요소만 사용합니다.

  • UI 컨트롤러
  • 모델 및 LiveData 보기
  • Room 데이터베이스

이 Codelab에서는 개발자가 프래그먼트와 탐색 파일을 사용하여 탐색을 구현하는 방법을 알고 있다고 가정합니다. 작업을 저장하기 위해 이 코드가 상당히 많이 제공됩니다.

1단계: 코드 검사

  1. 시작하려면 마지막 Codelab을 마칠 때 작성한 코드를 계속 사용하거나 시작 코드를 다운로드하세요.
  2. 시작 코드에서 SleepQualityFragment를 검사합니다. 이 클래스는 레이아웃을 확장하고 애플리케이션을 가져오며 binding.root를 반환합니다.
  3. 디자인 편집기에서 navigation.xml을 엽니다. SleepTrackerFragment에서 SleepQualityFragment로 이동한 후 SleepQualityFragment에서 SleepTrackerFragment로 다시 이동하는 경로가 있습니다.



  4. navigation.xml의 코드를 검사합니다. 특히 이름이 sleepNightKey<argument>을 찾아보세요.

    사용자가 SleepTrackerFragment에서 SleepQualityFragment,로 이동하면 업데이트해야 하는 밤에 앱에서 sleepNightKeySleepQualityFragment에 전달합니다.

2단계: 수면의 질 추적을 위한 탐색 추가

탐색 그래프에는 이미 SleepTrackerFragment에서 SleepQualityFragment로의 경로가 포함되어 있습니다. 그러나 한 프래그먼트에서 다음 프래그먼트로의 탐색을 구현하는 클릭 핸들러는 아직 코딩되지 않았습니다. 이제 ViewModel에 코드를 추가합니다.

클릭 핸들러에서 앱이 다른 대상으로 이동할 때 변경되는 LiveData를 설정합니다. 프래그먼트는 이 LiveData를 관찰합니다. 데이터가 변경되면 프래그먼트는 대상으로 이동하여 뷰 모델에 완료되었음을 알리고 상태 변수를 재설정합니다.

  1. SleepTrackerViewModel를 엽니다. 사용자가 Stop 버튼을 탭하면 앱이 SleepQualityFragment로 이동하여 품질 평점을 수집하도록 탐색을 추가해야 합니다.
  2. SleepTrackerViewModel에서 앱이 SleepQualityFragment로 이동하려고 할 때 변경되는 LiveData를 만듭니다. 캡슐화를 사용하여 LiveData의 가져오기 가능한 버전만 ViewModel에 노출합니다.

    이 코드는 수업 본문의 최상위 수준에 아무 곳에나 배치할 수 있습니다.
private val _navigateToSleepQuality = MutableLiveData<SleepNight>()

val navigateToSleepQuality: LiveData<SleepNight>
   get() = _navigateToSleepQuality
  1. 탐색을 트리거하는 변수를 재설정하는 doneNavigating() 함수를 추가합니다.
fun doneNavigating() {
   _navigateToSleepQuality.value = null
}
  1. Stop 버튼의 클릭 핸들러에서 onStopTracking()SleepQualityFragment로 이동을 트리거합니다. 함수의 끝부분에 있는 _navigateToSleepQuality 변수를 launch{} 블록 내의 마지막 항목으로 설정합니다. 이 변수는 night로 설정됩니다. 이 변수에 값이 있으면 앱이 SleepQualityFragment로 이동하여 밤을 전달합니다.
_navigateToSleepQuality.value = oldNight
  1. SleepTrackerFragment는 앱이 탐색 시기를 알 수 있도록 _navigateToSleepQuality를 관찰해야 합니다. SleepTrackerFragmentonCreateView()에서 navigateToSleepQuality()의 관찰자를 추가합니다. 이 가져오기가 명확하지 않아 androidx.lifecycle.Observer를 가져와야 합니다.
sleepTrackerViewModel.navigateToSleepQuality.observe(this, Observer {
})

  1. 관찰자 블록 내에서 현재 밤의 ID를 따라 이동한 후 doneNavigating()를 호출합니다. 가져오기가 명확하지 않으면 androidx.navigation.fragment.findNavController를 가져옵니다.
night ->
night?.let {
   this.findNavController().navigate(
           SleepTrackerFragmentDirections
                   .actionSleepTrackerFragmentToSleepQualityFragment(night.nightId))
   sleepTrackerViewModel.doneNavigating()
}
  1. 앱을 빌드하고 실행합니다. Start(시작)를 탭한 다음 Stop(중지)을 탭하면 SleepQualityFragment 화면으로 이동합니다. 돌아가려면 시스템 뒤로 버튼을 사용합니다.

이 작업에서는 수면의 질을 기록하고 수면 추적기 프래그먼트로 다시 이동합니다. 디스플레이가 자동으로 업데이트되어 사용자에게 업데이트된 값이 표시됩니다. ViewModelViewModelFactory를 만들고 SleepQualityFragment를 업데이트해야 합니다.

1단계: ViewModel 및 ViewModelFactory 만들기

  1. sleepquality 패키지에서 SleepQualityViewModel.kt를 만들거나 엽니다.
  2. sleepNightKey 및 데이터베이스를 인수로 사용하는 SleepQualityViewModel 클래스를 만듭니다. SleepTrackerViewModel의 경우와 마찬가지로 팩토리에서 database를 전달해야 합니다. 탐색 메뉴에서 sleepNightKey도 전달해야 합니다.
class SleepQualityViewModel(
       private val sleepNightKey: Long = 0L,
       val database: SleepDatabaseDao) : ViewModel() {
}
  1. SleepQualityViewModel 클래스 내에서 JobuiScope를 정의하고 onCleared()를 재정의합니다.
private val viewModelJob = Job()
private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)

override fun onCleared() {
   super.onCleared()
   viewModelJob.cancel()
}
  1. 위와 동일한 패턴을 사용하여 SleepTrackerFragment로 다시 이동하려면 _navigateToSleepTracker를 선언합니다. navigateToSleepTrackerdoneNavigating()를 구현합니다.
private val _navigateToSleepTracker = MutableLiveData<Boolean?>()

val navigateToSleepTracker: LiveData<Boolean?>
   get() = _navigateToSleepTracker

fun doneNavigating() {
   _navigateToSleepTracker.value = null
}
  1. 모든 수면 품질 이미지를 사용할 수 있도록 클릭 핸들러 onSetSleepQuality()를 만듭니다.

    이전 Codelab과 동일한 코루틴 패턴을 사용합니다.
  • uiScope에서 코루틴을 실행하고 I/O 디스패처로 전환합니다.
  • sleepNightKey를 사용하여 tonight를 가져옵니다.
  • 수면의 질을 설정합니다.
  • 데이터베이스를 업데이트합니다.
  • 탐색을 트리거합니다.

아래 코드 샘플은 다른 컨텍스트에서 데이터베이스 작업을 감안하는 대신 클릭 핸들러의 모든 작업을 수행합니다.

fun onSetSleepQuality(quality: Int) {
        uiScope.launch {
            // IO is a thread pool for running operations that access the disk, such as
            // our Room database.
            withContext(Dispatchers.IO) {
                val tonight = database.get(sleepNightKey) ?: return@withContext
                tonight.sleepQuality = quality
                database.update(tonight)
            }

            // Setting this state variable to true will alert the observer and trigger navigation.
            _navigateToSleepTracker.value = true
        }
    }
  1. sleepquality 패키지에서 SleepQualityViewModelFactory.kt를 만들거나 열고 아래와 같이 SleepQualityViewModelFactory 클래스를 추가합니다. 이 클래스는 이전에 본 것과 동일한 상용구 코드의 버전을 사용합니다. 계속 진행하기 전에 코드를 검사합니다.
class SleepQualityViewModelFactory(
       private val sleepNightKey: Long,
       private val dataSource: SleepDatabaseDao) : ViewModelProvider.Factory {
   @Suppress("unchecked_cast")
   override fun <T : ViewModel?> create(modelClass: Class<T>): T {
       if (modelClass.isAssignableFrom(SleepQualityViewModel::class.java)) {
           return SleepQualityViewModel(sleepNightKey, dataSource) as T
       }
       throw IllegalArgumentException("Unknown ViewModel class")
   }
}

2단계: SleepQualityFragment 업데이트

  1. SleepQualityFragment.kt를 엽니다.
  2. onCreateView()에서 application를 가져온 후 탐색과 함께 제공된 arguments를 가져와야 합니다. 이 인수는 SleepQualityFragmentArgs에 있습니다. 번들에서 추출해야 합니다.
val arguments = SleepQualityFragmentArgs.fromBundle(arguments!!)
  1. 다음으로 dataSource을 가져옵니다.
val dataSource = SleepDatabase.getInstance(application).sleepDatabaseDao
  1. 팩토리를 만들어 dataSourcesleepNightKey를 전달합니다.
val viewModelFactory = SleepQualityViewModelFactory(arguments.sleepNightKey, dataSource)
  1. ViewModel 참조를 가져옵니다.
val sleepQualityViewModel =
       ViewModelProviders.of(
               this, viewModelFactory).get(SleepQualityViewModel::class.java)
  1. ViewModel를 결합 객체에 추가합니다. 결합 객체에 오류가 표시되면 지금은 무시합니다.
binding.sleepQualityViewModel = sleepQualityViewModel
  1. 관찰자를 추가합니다. 메시지가 표시되면 androidx.lifecycle.Observer를 가져옵니다.
sleepQualityViewModel.navigateToSleepTracker.observe(this, Observer {
   if (it == true) { // Observed state is true.
       this.findNavController().navigate(
               SleepQualityFragmentDirections.actionSleepQualityFragmentToSleepTrackerFragment())
       sleepQualityViewModel.doneNavigating()
   }
})

3단계: 레이아웃 파일 업데이트 및 앱 실행하기

  1. fragment_sleep_quality.xml 레이아웃 파일을 엽니다. <data> 블록에서 SleepQualityViewModel의 변수를 추가합니다.
 <data>
       <variable
           name="sleepQualityViewModel"
           type="com.example.android.trackmysleepquality.sleepquality.SleepQualityViewModel" />
   </data>
  1. 6개의 수면 품질 이미지마다 각각 아래와 같은 클릭 핸들러를 추가합니다. 품질 평점을 이미지에 맞춥니다.
android:onClick="@{() -> sleepQualityViewModel.onSetSleepQuality(5)}"
  1. 프로젝트를 정리하고 다시 빌드합니다. 그러면 결합 객체 오류가 해결됩니다. 그 외의 경우 캐시 (File > Ininvalid Caches / Restart)를 지운 다음 앱을 다시 빌드합니다.

수고하셨습니다. 코루틴을 사용하여 전체 Room 데이터베이스 앱을 빌드했습니다.

이제 앱이 원활하게 작동합니다. 사용자는 시작중지를 원하는 만큼 탭할 수 있습니다. 사용자가 중지를 탭하면 수면의 질을 입력할 수 있습니다. 사용자가 지우기를 탭하면 모든 데이터가 백그라운드에서 자동으로 삭제됩니다. 그러나 모든 버튼은 항상 사용 설정되어 있고 클릭 가능합니다. 이로 인해 앱이 중단되지는 않지만 사용자가 불완전한 수면 밤을 만들 수 있습니다.

마지막 작업에서는 변환 지도를 사용하여 사용자가 올바른 옵션을 선택할 수 있도록 버튼 표시 여부를 관리하는 방법을 알아봅니다. 모든 데이터가 삭제된 후 이와 유사한 방법으로 호환 메시지를 표시할 수 있습니다.

1단계: 버튼 상태 업데이트

시작 시에는 시작 버튼만 사용 설정되어 클릭할 수 있도록 버튼 상태를 설정하는 것이 좋습니다.

사용자가 시작을 탭하면 중지 버튼이 사용 설정되고 시작은 사용 설정되지 않습니다. 지우기 버튼은 데이터베이스에 데이터가 있는 경우에만 사용 설정됩니다.

  1. fragment_sleep_tracker.xml 레이아웃 파일을 엽니다.
  2. 각 버튼에 android:enabled 속성을 추가합니다. android:enabled 속성은 버튼의 사용 설정 여부를 나타내는 부울 값입니다. 사용 설정됨 버튼을 탭할 수 있습니다. 사용 중지된 버튼은 탭할 수 있습니다. 잠시 후에 정의하는 상태 변수의 값을 속성에 제공합니다.

start_button:

android:enabled="@{sleepTrackerViewModel.startButtonVisible}"

stop_button:

android:enabled="@{sleepTrackerViewModel.stopButtonVisible}"

clear_button:

android:enabled="@{sleepTrackerViewModel.clearButtonVisible}"
  1. SleepTrackerViewModel를 열고 해당하는 변수 3개를 만듭니다. 각 변수를 테스트하는 변환을 할당합니다.
  • tonightnull인 경우 시작 버튼을 사용 설정해야 합니다.
  • tonightnull가 아니면 중지 버튼을 사용 설정해야 합니다.
  • 지우기 버튼은 nights와 함께 데이터베이스에 절전 모드가 있는 경우에만 사용 설정해야 합니다.
val startButtonVisible = Transformations.map(tonight) {
   it == null
}
val stopButtonVisible = Transformations.map(tonight) {
   it != null
}
val clearButtonVisible = Transformations.map(nights) {
   it?.isNotEmpty()
}
  1. 앱을 실행하고 버튼을 사용하여 실험합니다.

2단계: 스낵바를 사용하여 사용자에게 알림

사용자가 데이터베이스를 삭제하면 Snackbar 위젯을 사용하여 사용자에게 확인 메시지를 표시합니다. 스낵바는 화면 하단의 메시지를 통해 작업에 관한 간단한 피드백을 제공합니다. 스낵바는 시간이 초과되거나 사용자가 화면의 다른 곳에서 상호작용하거나 사용자가 스낵바를 화면에서 스와이프한 후에 사라집니다.

스낵바 표시는 UI 작업이며 프래그먼트에서 발생해야 합니다. 스낵바 표시 결정은 ViewModel에서 발생합니다. 데이터가 삭제될 때 스낵바를 설정하고 트리거하려면 탐색을 트리거하는 것과 동일한 기법을 사용하면 됩니다.

  1. SleepTrackerViewModel에서 캡슐화된 이벤트를 만듭니다.
private var _showSnackbarEvent = MutableLiveData<Boolean>()

val showSnackBarEvent: LiveData<Boolean>
   get() = _showSnackbarEvent
  1. 그런 다음 doneShowingSnackbar()를 구현합니다.
fun doneShowingSnackbar() {
   _showSnackbarEvent.value = false
}
  1. SleepTrackerFragmentonCreateView()에서 관찰자를 추가합니다.
sleepTrackerViewModel.showSnackBarEvent.observe(this, Observer { })
  1. 관찰자 블록 내부에 스낵바를 표시하고 이벤트를 즉시 재설정합니다.
   if (it == true) { // Observed state is true.
       Snackbar.make(
               activity!!.findViewById(android.R.id.content),
               getString(R.string.cleared_message),
               Snackbar.LENGTH_SHORT // How long to display the message.
       ).show()
       sleepTrackerViewModel.doneShowingSnackbar()
   }
  1. SleepTrackerViewModelonClear() 메서드에서 이벤트를 트리거합니다. 이렇게 하려면 launch 블록 내에 이벤트 값을 true로 설정합니다.
_showSnackbarEvent.value = true
  1. 앱을 빌드하고 실행합니다.

Android 스튜디오 프로젝트: TrackMySleepQualityFinal

이 앱에서 수면 상태 추적을 구현하는 것은 새로운 키로 익숙한 음악을 재생하는 것과 같습니다. 세부정보는 변경되지만 이 과정의 이전 Codelab에서 한 기본 패턴이 그대로 유지됩니다. 이러한 패턴을 인식하면 기존 앱의 코드를 재사용할 수 있으므로 코딩 속도가 훨씬 빨라집니다. 지금까지 이 과정에서 사용한 패턴은 다음과 같습니다.

  • ViewModelViewModelFactory를 만들고 데이터 소스를 설정합니다.
  • 탐색을 트리거합니다. 관심사를 분리하려면 뷰 모델에 클릭 핸들러를 배치하고 프래그먼트에 탐색을 배치합니다.
  • LiveData로 캡슐화를 사용하여 상태 변경을 추적하고 적절히 대응하세요.
  • LiveData과 함께 변환을 사용합니다.
  • 싱글톤 데이터베이스를 만듭니다.
  • 데이터베이스 작업의 코루틴을 설정합니다.

내비게이션 실행

탐색 파일에서 프래그먼트 간 가능한 탐색 경로를 정의합니다. 한 프래그먼트에서 다른 프래그먼트로의 탐색을 트리거하는 방법에는 여러 가지가 있습니다. 예를 들면 다음과 같습니다.

  • onClick 핸들러를 정의하여 대상 프래그먼트로의 탐색을 트리거합니다.
  • 또는 한 프래그먼트에서 다음 프래그먼트로의 이동을 사용 설정하려면 다음을 실행하세요.
  • 탐색이 발생해야 할 때 기록할 LiveData 값을 정의합니다.
  • LiveData 값에 관찰자를 연결합니다.
  • 그런 다음 탐색이 트리거되거나 완료될 때마다 코드에서 이 값을 변경합니다.

android:enabled 속성 설정

  • android:enabled 속성은 TextView에 정의되며 Button를 비롯한 모든 서브클래스에 상속됩니다.
  • android:enabled 속성은 View의 사용 여부를 결정합니다. 'enabled'의 의미는 서브클래스에 따라 다릅니다. 예를 들어 EditText가 사용 설정되지 않으면 사용자가 포함된 텍스트를 수정하지 못하게 되고, Button가 사용 설정되지 않으면 사용자가 버튼을 탭할 수 없게 됩니다.
  • enabled 속성은 visibility 속성과 다릅니다.
  • 변환 맵을 사용하여 다른 객체 또는 변수의 상태에 따라 버튼의 enabled 속성 값을 설정할 수 있습니다.

이 Codelab에서 다루는 다른 사항은 다음과 같습니다.

  • 사용자에게 알림을 트리거하려면 탐색을 트리거하는 데 사용하는 것과 동일한 기법을 사용하면 됩니다.
  • Snackbar를 사용하여 사용자에게 알릴 수 있습니다.

Udacity 과정:

Android 개발자 문서:

이 섹션에는 강사가 진행하는 과정의 일부로 이 Codelab을 통해 작업하는 학생들의 숙제 과제가 나와 있습니다. 강사는 다음을 처리합니다.

  • 필요한 경우 과제를 할당합니다.
  • 학생에게 과제 과제를 제출하는 방법을 알려주세요.
  • 과제 과제를 채점합니다.

강사는 이러한 추천을 원하는 만큼 사용할 수 있으며 다른 적절한 숙제를 할당해도 좋습니다.

이 Codelab을 직접 학습하고 있다면 언제든지 숙제를 통해 지식을 확인해 보세요.

답변

질문 1

앱이 한 프래그먼트에서 다른 프래그먼트로의 탐색을 트리거하도록 사용 설정하는 한 가지 방법은 LiveData 값을 사용하여 탐색을 트리거할지 여부를 나타내는 것입니다.

빨간색 프래그먼트에서 파란색 프래그먼트로의 탐색을 트리거하기 위해 LiveData 값(gotoBlueFragment)을 사용하는 단계는 무엇인가요? 해당하는 항목을 모두 선택해 주세요.

  • ViewModel에서 LiveDatagotoBlueFragment를 정의합니다.
  • RedFragment에서 gotoBlueFragment 값을 확인합니다. 필요한 경우 observe{} 코드를 구현하여 BlueFragment로 이동한 다음 gotoBlueFragment 값을 재설정하여 탐색이 완료되었음을 나타냅니다.
  • 앱이 RedFragment에서 BlueFragment로 이동해야 할 때마다 탐색을 트리거하는 값으로 gotoBlueFragment 변수를 설정해야 합니다.
  • 코드에서 사용자가 BlueFragment로 이동하기 위해 클릭하는 ViewonClick 핸들러를 정의해야 합니다. 여기서 onClick 핸들러는 goToBlueFragment 값을 관찰합니다.

질문 2

LiveData를 사용하여 Button의 사용 설정 (클릭 가능) 여부를 변경할 수 있습니다. 앱이 UpdateNumber 버튼을 변경하도록 하려면 어떻게 해야 하나요?

  • myNumber 값이 5보다 크면 버튼이 사용 설정됩니다.
  • myNumber가 5 이하인 경우 버튼이 사용 설정되지 않았습니다.

UpdateNumber 버튼이 포함된 레이아웃에 다음과 같이 NumbersViewModel<data> 변수가 포함되어 있다고 가정합니다.

<data>
   <variable
       name="NumbersViewModel"
       type="com.example.android.numbersapp.NumbersViewModel" />
</data>

레이아웃 파일의 버튼 ID는 다음과 같습니다.

android:id="@+id/update_number_button"

추가로 취해야 할 조치 해당하는 보기를 모두 선택하세요.

  • NumbersViewModel 클래스에서 숫자를 나타내는 LiveData 변수 myNumber을 정의합니다. 또한 myNumber 변수에서 Transform.map()를 호출하여 값이 설정된 변수를 정의합니다. 이 변수는 숫자가 5보다 큰지 여부를 나타내는 부울을 반환합니다.

    특히 ViewModel에서 다음 코드를 추가합니다.
val myNumber: LiveData<Int>

val enableUpdateNumberButton = Transformations.map(myNumber) {
   myNumber > 5
}
  • XML 레이아웃에서 update_number_button buttonandroid:enabled 속성을 NumberViewModel.enableUpdateNumbersButton로 설정합니다.
android:enabled="@{NumbersViewModel.enableUpdateNumberButton}"
  • NumbersViewModel 클래스를 사용하는 Fragment에서 버튼의 enabled 속성에 관찰자를 추가합니다.

    특히 Fragment에서 다음 코드를 추가합니다.
// Observer for the enabled attribute
viewModel.enabled.observe(this, Observer<Boolean> { isEnabled ->
   myNumber > 5
})
  • 레이아웃 파일에서 update_number_button buttonandroid:enabled 속성을 "Observable"로 설정합니다.

다음 과정 7.1 RecyclerView 기초를 시작해 보세요.

이 과정의 다른 Codelab 링크는 Android Kotlin 기초 Codelab 방문 페이지를 참고하세요.