Coroutine, Room, Livedata 의 궁금.
부캠에 붙고 방 이사하고 근로 인수인계 등등하느라 며칠 공부를 잘 안 했는데
방금 조금 하면서 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
- 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를 사용하면 업데이트 코드를 자동으로 생성하고 background에서 비동기적으로 실행해준다.