liveData Builder

최희창·2022년 9월 20일

Introduction

viewModelScope.launch{} 대신 live data builder를 사용해보도록 합니다.

viewModelScope

init {
        loadTopTwoDogsAsync()
    }

private fun loadTopTwoDogsAsync() {
        viewModelScope.launch {
            logCoroutine("loadTopTwoDogsAsync", coroutineContext)
            val list = runCatching { mainActivityRepository.getTopTwoDogsAsync() }
            list.onSuccess {
                _topDogsAsync.value = it.value
            }.onFailure {
                _snackbar.value = it.message.toString()
                _snackbar.value = "loadTopTwoDogsAsync() " + it.message.toString()
            }
        }
    }
  • mainActivityRepository.getTopTwoDogsAsync()는 Background에서 실행되는 suspend 함수입니다.
viewModel.topDogsAsync.observe(this, Observer {
            //Do Something
        })
  • View에서 live data를 observe하고 있습니다.

liveData

  • live data builder는 Live Data와 Coroutines의 차이점을 채워줍니다.
val liveDataResult = liveData {
        emit(GeneralResult.Progress(true))
        //This below function is a suspend function
        val topTwoDogsResult = mainActivityRepository.getTopTwoDogsAsync()
        emit(GeneralResult.SuccessGeneric(topTwoDogsResult.value))
    }
  • 처음에는 livedata의 결과로 GeneralResult.Progress(true)로 리턴이 되고 이후 suspend 함수가 실행이 됩니다.
  • 해당 함수에서 값을 받아올 때까지 중단되며 이후에 livedata의 결과로 topTwoDogsResult가 리턴됩니다.
viewModel.liveDataResult.observe(this, Observer {
            when (it) {
                is GeneralResult.Progress -> { }
                is GeneralResult.SuccessGeneric<*> -> { }
                is GeneralResult.Error -> { }
            }
        })
  • view에서의 live data result를 observe하고 있습니다.

live data는 어떻게 동작할까요?

  1. 코루틴은 Live Data가 active 되었을 때만 동작합니다. 이는 최소한 하나의 observer(active)가 필요함을 의미합니다.
  2. 코루틴이 실행되는 도중 Live data가 inactive된다면 최소한의 시간을 기다리고, 여전히 observer가 존재하지 않는다면 코루틴은 취소됩니다.
  3. 취소 이후에 live data가 active된다면 재실행됩니다. 만약 완료되었거나 exception이 발생했다면 재시작하지 않습니다.
  4. 기본적으로 main thread에서 실행되나 liveData(Dispatchers.IO) {}으로 switching 할 수 있습니다.
  5. emit()은 어느 thread에서나 실행될 수 있습니다.

viewModelScope 대신에 써야만 할까요?

  • 정해진 것은 없으나 live data builder를 썼을 시 코드가 깔끔해지고 구현하기가 쉽습니다.
  • 하지만 view와 독립적인 코루틴을 실행해야 할 때는 viewModelScope.launch{}가 필요합니다. (공유된 viewModel을 사용하는 경우 or 뷰에서의 observer가 제거되었을때도 동작을 해야하는 경우 or live data가 unactive되었을때도 동작해야 하는 경우 가 있습니다.)

live data를 Emitting 하려면?

  • emitSource를 사용할 수 있습니다.
    val liveDataResult = liveData {
        logCoroutineThreadNameOnly("liveDataResult")
        emit(GeneralResult.Progress(true))
        emitSource(getTopTwoDogsLiveData())
    }

    private fun getTopTwoDogsLiveData(): LiveData<GeneralResult> = liveData {
        while (true) {
            delay(DELAY_BETWEEN_DOGS_IN_MS)
            val topTwoDogsResult = mainActivityRepository.getTopTwoDogsAsync()
            emit(topTwoDogsResult)
        }
    }
profile
heec.choi

0개의 댓글