Android

Coroutine, Room, Livedata 의 궁금.

jhg3410 2022. 7. 15. 00:43

부캠에 붙고 방 이사하고 근로 인수인계 등등하느라 며칠 공부를 잘 안 했는데 

방금 조금 하면서 Coroutine, Room, Livedata에 느낀점

 

몇 가지 의문점에 대한 해답

 

궁금증 1

suspend fun refreshVideos() {
        withContext(Dispatchers.IO) {
            Timber.d("refresh video is called")
            val playList = DevByteNetwork.devbytes.getPlaylist()
            database.videoDao.insertAll(playList.asDatabaseModel())
        }
    }

 

여기서 왜 withContext로 IO Dispatchers로 스위칭 해줄까 궁금했다.

suspend를 사용하면 retrofit 도 room 도 자동으로 비동기 처리를 해주기 때문에 스위칭 이유가 없지 않을까?

 

해답: retrofit을 하면 저 부분만 IO 스레드로 가서 일하고 다시 Main으로 오기 때문에 결국 Room 관련은 Main이 해서 에러가 발생 그래서 첨부터 스위칭을 해줘야 한다.(확실하진 않다...)

 

 

궁금증 2

viewModelScope.launch {
    try {
        videosRepository.refreshVideos()
        _eventNetworkError.value = false
        _isNetworkErrorShown.value = false

 

자 여기서 refreshVideos에 delay 2초를 걸면  밑에 변수값 변경은 2초 뒤에 일어날까 궁금했다.

 

답: 그렇다 2초 뒤다 순차적으로 처리해준다. 

refreshVideos는 IO에서 하는데 왜 Main에서 변수값 변경도 2초 뒤에 되나 그게 코루틴의 효과다

Main이 일시중지되면 다른 Coroutine이 Main에서 일을 하면 그동안 일을 한다.

init {
        refreshDataFromRepository()
        viewModelScope.launch {
            while (true){
                delay(1000)
                Timber.d("1")
            }
        }
    }

이렇게 실험해봤다.

시도해보면 조흔 블로그 https://kotlinworld.com/144?category=973476 

 

[Coroutine] 5. suspend fun의 이해

일시중단 가능한 코루틴 코루틴은 기본적으로 일시중단 가능하다. launch로 실행하든 async로 실행하든 내부에 해당 코루틴을 일시중단 해야하는 동작이 있으면 코루틴은 일시 중단된다. 예시로

kotlinworld.com

 

  • To keep the UI running smoothly, use coroutines for long-running tasks, such as all database operations.
  • Coroutines are asynchronous and non-blocking. They use suspend functions to make asynchronous code sequential.
  • When a coroutine calls a function marked with suspend, instead of blocking until that function returns like a normal function call, it suspends execution until the result is ready. Then it resumes where it left off with the result.
  • The difference between blocking and suspending is that if a thread is blocked, no other work happens. If the thread is suspended, other work happens until the result is available.

읽어보면 조흔 말씀

 

 

궁금증 3

val videos : LiveData<List<DevByteVideo>> = Transformations.map(database.videoDao.getVideos()){
    it.asDomainModel()
}

 

val playlist = videosRepository.videos

위의 videos는 videoRepository  클래스 내부에 있고 room에서 get 해 DomainModel로 변경한 변수이다.

 

이게 가능한가?

suspend를 사용하면 room 이 IO에서 일을 해준다지만 

저렇게 그냥 사용이 가능한가?

 

고민을 하다 

@Query("select * from databasevideo")
fun getVideos(): LiveData<List<DatabaseVideo>>

@Query("select * from databasevideo")
fun getTestVideos(): List<DatabaseVideo>

 

Test쿼리를 만들어서 테스트해본 결과 얘는 에러가 뜬다 (흔히 볼 수 있는 오래 걸리는 일은 MainThread에서 하지 마라)

 

그럼 차이점은 LiveData이다 그래서 찾아봤다.

 

 

Room generates all the necessary code to update the LiveData object when a database is updated. The generated code runs the query asynchronously on a background thread when needed. This pattern is useful for keeping the data displayed in a UI in sync with the data stored in a database.

https://developer.android.com/topic/libraries/architecture/livedata#use_livedata_with_room

 

LiveData 개요  |  Android 개발자  |  Android Developers

LiveData를 사용하여 수명 주기를 인식하는 방식으로 데이터를 처리합니다.

developer.android.com

 

와우 LiveData를 사용하면 업데이트 코드를 자동으로 생성하고 background에서 비동기적으로  실행해준다.