코드랩 Room 사용하기3

1 minute read

SleepTrackerFragment화면에서 STOP버튼을 누르면 SleepQualityFragment로 넘어가서 Quality를 설정해줘야한다.

SleepTrackerViewModel

private val _navigateToSleepQuality = MutableLiveData<SleepNight>()  
val navigateToSleepQuality: LiveData<SleepNight>  
  get() = _navigateToSleepQuality

그리고 STOP버튼을 누르면 중단했을때의 oldNight 객체를 넣어준다.

fun onStop(){  
  viewModelScope.launch {  
  val oldNight = _tonight.value?:return@launch  
        oldNight.endTimeMilli = System.currentTimeMillis()  
  update(oldNight)  
  _navigateToSleepQuality.value = oldNight  
  
    }  
}
fun doneNavigating() {  
  _navigateToSleepQuality.value = null  
}

이 코드는 프래그먼트 이동 후 null로 초기화해주는 코드이다.

SleepTrackerFragment에서는navigateToSleepQuality를 관찰하고 있다가. 값이 변경되면 SleepQualityFragment로 이동한다. SleepTrackerFragment

viewModel.navigateToSleepQuality.observe(viewLifecycleOwner, Observer { night ->  
  night?.let {  
  this.findNavController().navigate(  
  SleepTrackerFragmentDirections  
  .actionSleepTrackerFragmentToSleepQualityFragment(night.nightId))  
    viewModel.doneNavigating()  
  }  
})

관찰하고 있던 navigateToSleepQuality의 값은 STOP에서 넣어줬던 oldNight 객체이다. 그 객체의 Id를 넘겨서 해당 id 사용해서 컬럼의 sleepQuality를 입력하고 update 해야하기 때문에 필요하다.


SleepQualityFragment를 사용하기 위해 SleepQualityViewModel을 만든다.

SleepTrackerFragment에서 넘겨준 key와 databaseDao를 사용하기 위해 viewModelProvider 를 만들어준다.

SleepQualityViewModelFactory

class SleepQualityViewModelFactory(private val sleepNightKey:Long = 0L,  
                                    private val dataSource: SleepDatabaseDao):ViewModelProvider.Factory{  
  @Suppress("uncheked_cast")  
  override fun <T : ViewModel?> create(modelClass: Class<T>): T {  
  if(modelClass.isAssignableFrom(SleepQualityViewModel::class.java)){  
  return SleepQualityViewModel(sleepNightKey,dataSource) as T  
  }  
  
  throw IllegalArgumentException("Unkown ViewModel Class")  
 }  
  
}

만들어준 viewModelFactory를 사용해서 viewModel을 만들어준다.

SleepQualityFragment

class SleepQualityFragment : Fragment() {  
  override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,  
                              savedInstanceState: Bundle?): View? {  
  
  // Get a reference to the binding object and inflate the fragment views.  
  val binding: FragmentSleepQualityBinding = DataBindingUtil.inflate(  
  inflater, R.layout.fragment_sleep_quality, container, false)  
  
  //SleepTrackerFragment에서 넘겨준 값  
  val arguments = SleepQualityFragmentArgs.fromBundle(requireArguments())  
  //Database객체를 얻어올때 사용되는 application  val application = requireNotNull(this.activity).application  
  //Dao  
  val dataSource = SleepDatabase.getInstance(application).sleepDatabaseDao  
        //넘겨받은 키값과 dao를 사용해 viewModelProvider 생성  
  val viewModelProvider = SleepQualityViewModelFactory(arguments.sleepNightKey,dataSource)  
  //만든 viewModelProvider를 사용해서 viewModel 생성  
  val viewModel = ViewModelProvider(this,viewModelProvider).get(SleepQualityViewModel::class.java)  
  
  //바인딩  
  binding.viewModel = viewModel  
        binding.lifecycleOwner = viewLifecycleOwner  
    
  return binding.root  
  }  
}

SleepTrackerFragment로 부터 넘겨받은 id와 Dao객체로 viewModelProvider가 만들어졌고, viewModelProvider로 viewModel도 만들었다. 그리고 데이터바인딩도 해줬다.


스크린샷 2021-02-03 오후 11 42 02

SleepQualityFragment에서 Quality를 선택하고 다시 SleepTrackerFragment로 넘어가야하기 때문에

viewModel에 다음 코드를 추가해준다.

private val _navigateToSleepTracker = MutableLiveData<Boolean?>()  
val navigateToSleepTracker : LiveData<Boolean?>  
get() = _navigateToSleepTracker
fun doneNavigating() {  
  _navigateToSleepTracker.value = null  
}
fun onSetSleepQuality(quality:Int){  
  viewModelScope.launch {  
  val tonight = database.get(sleepNightKey) ?: return@launch  
        tonight.sleepQuality = quality  
  database.update(tonight)  
  _navigateToSleepTracker.value = true  
  }  
}

SleepQualityFragment에서 navigateToSleepTracker를 관찰하고 있다가 Quailty를 선택하면 _navigateToSleepTracker.value = true가 되면서 다시 SleepTrackerFragment로 돌아간다.

viewModel.navigateToSleepTracker.observe(viewLifecycleOwner, Observer {  
  if (it == true) { // Observed state is true.  
  this.findNavController().navigate(  
  SleepQualityFragmentDirections.actionSleepQualityFragmentToSleepTrackerFragment())  
  viewModel.doneNavigating()  
 }})

Comments