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를 빌드합니다.

앱에는 프래그먼트로 표현되는 두 개의 화면이 있습니다(아래 그림 참고).

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

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

사용자의 흐름은 다음과 같습니다.

  • 사용자가 앱을 열면 수면 추적 화면이 표시됩니다.
  • 사용자가 시작 버튼을 탭합니다. 시작 시간을 기록하고 표시합니다. 시작 버튼은 사용 중지되고 중지 버튼은 사용 설정됩니다.
  • 사용자가 중지 버튼을 탭합니다. 이렇게 하면 종료 시간이 기록되고 수면의 질 화면이 열립니다.
  • 사용자가 수면의 질 아이콘을 선택합니다. 화면이 닫히고 추적 화면에 수면 종료 시간과 수면의 질이 표시됩니다. 중지 버튼은 사용 중지되고 시작 버튼은 사용 설정됩니다. 앱이 또 다른 밤을 맞이할 준비가 되었습니다.
  • 데이터베이스에 데이터가 있으면 언제든지 지우기 버튼이 사용 설정됩니다. 사용자가 지우기 버튼을 탭하면 모든 데이터가 복구할 수 없이 삭제됩니다. '정말로 지우시겠습니까?' 메시지가 표시되지 않습니다.

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

  • 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를 엽니다. 사용자가 중지 버튼을 탭하면 앱이 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. 중지 버튼 onStopTracking()의 클릭 핸들러에서 SleepQualityFragment로의 탐색을 트리거합니다. 함수 끝에서 _navigateToSleepQuality 변수를 launch{} 블록 내의 마지막 항목으로 설정합니다. 이 변수는 night로 설정됩니다. 이 변수에 값이 있으면 앱이 SleepQualityFragment로 이동하여 night.
    을 전달합니다.
_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. 앱을 빌드하고 실행합니다. 시작을 탭한 다음 중지를 탭하면 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 > Invalidate Caches / Restart) 앱을 다시 빌드합니다.

축하합니다. 코루틴을 사용하여 완전한 Room 데이터베이스 앱을 빌드했습니다.

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

이 마지막 작업에서는 변환 맵을 사용하여 사용자가 올바른 선택만 할 수 있도록 버튼 표시 상태를 관리하는 방법을 알아봅니다. 모든 데이터가 삭제된 후 친근한 메시지를 표시하는 데도 비슷한 방법을 사용할 수 있습니다.

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

처음에는 Start(시작) 버튼만 사용 설정되어 클릭할 수 있도록 버튼 상태를 설정해야 합니다.

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

  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를 열고 세 개의 해당 변수를 만듭니다. 각 변수에 변환을 할당하여 변수를 테스트합니다.
  • 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. SleepTrackerViewModel에서 onClear() 메서드의 이벤트를 트리거합니다. 이렇게 하려면 launch 블록 내에서 이벤트 값을 true로 설정합니다.
_showSnackbarEvent.value = true
  1. 앱을 빌드하고 실행합니다.

Android 스튜디오 프로젝트: TrackMySleepQualityFinal

이 앱에서 수면의 질 추적을 구현하는 것은 새로운 키로 익숙한 음악을 연주하는 것과 같습니다. 세부사항은 변경되지만 이 과정의 이전 Codelab에서 수행한 기본 패턴은 동일하게 유지됩니다. 이러한 패턴을 알고 있으면 기존 앱의 코드를 재사용할 수 있으므로 코딩이 훨씬 빨라집니다. 지금까지 이 과정에서 사용된 패턴은 다음과 같습니다.

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

탐색 트리거

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

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

android:enabled 속성 설정

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

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

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

Udacity 과정:

Android 개발자 문서:

이 섹션에는 강사가 진행하는 과정의 일부로 이 Codelab을 진행하는 학생에게 출제할 수 있는 과제가 나열되어 있습니다. 다음 작업은 강사가 결정합니다.

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

강사는 이러한 추천을 원하는 만큼 사용할 수 있으며 적절하다고 생각되는 다른 과제를 출제해도 됩니다.

이 Codelab을 직접 진행하는 경우 이러한 과제를 자유롭게 사용하여 배운 내용을 테스트해 보세요.

질문에 답하세요

질문 1

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

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

  • ViewModel에서 LiveDatagotoBlueFragment를 정의합니다.
  • RedFragment에서 gotoBlueFragment 값을 확인합니다. observe{} 코드를 구현하여 적절한 경우 BlueFragment로 이동한 다음 gotoBlueFragment 값을 재설정하여 탐색이 완료되었음을 나타냅니다.
  • 앱이 RedFragment에서 BlueFragment로 이동해야 할 때마다 코드가 gotoBlueFragment 변수를 탐색을 트리거하는 값으로 설정해야 합니다.
  • 사용자가 클릭하여 BlueFragment로 이동하는 View에 대해 코드가 onClick 핸들러를 정의해야 합니다. 여기서 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 방문 페이지를 참고하세요.