김호쭈
DevForYou
김호쭈
전체 방문자
오늘
어제
  • 분류 전체보기 (321)
    • • 데이터베이스(DB) (9)
      • __SQL__ (9)
    • •알고리즘(Algorithm ) (117)
      • 문제풀이 (99)
      • 스터디 (14)
      • 알고리즘 팁 (4)
    • •Compter Science (57)
      • Operating System (25)
      • Computer Network (1)
      • Computer Vision (16)
      • Artificial Intelligence (14)
      • Software Technology (1)
    • • 독서 (36)
      • Design Pattern (24)
      • 객체지향의 사실과 오해 (1)
      • Object Oriented Software En.. (11)
    • • 개발 (26)
      • React (3)
      • node.js (6)
      • Django (11)
      • Spring boot (6)
    • • 개발Tip (4)
      • GitHub (0)
    • •프로젝트 (2)
      • 물물 (2)
    • •App (54)
      • 안드로이드 with Kotlin (50)
      • 코틀린(Kotiln) (4)
    • •회고 (8)
    • •취준일기 (3)
    • • 기타 (2)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • Remote저장소
  • GitHubDesktop
  • ㄱ
  • local저장소
  • 깃허브데스크탑
  • KMU_WINK
  • 원격저장소
  • 로컬저장소

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
김호쭈

DevForYou

[안드로이드 코드랩/Room-2] 코루틴을 이용해 Room CRUD구현해보기, LiveData를 반환하는 DAO
•App/안드로이드 with Kotlin

[안드로이드 코드랩/Room-2] 코루틴을 이용해 Room CRUD구현해보기, LiveData를 반환하는 DAO

2022. 8. 21. 15:12

<이전글>

 

[안드로이드 코드랩] 안드로이드 Room-DB만들기, Entity개념, DAO

<코드랩 과정6: Room데이터베이스와 코루틴> Android Kotlin 기초  | 학습 과정  | Android Developers Android Kotlin 기초 Android Kotlin 기초 교육 과정은 Google Developers 교육팀에서 만들었습니다. 이..

devforyou.tistory.com

<코드랩>

 

Android Kotlin 기초  |  학습 과정  |  Android Developers

Android Kotlin 기초 Android Kotlin 기초 교육 과정은 Google Developers 교육팀에서 만들었습니다. 이 교육 과정에서는 Android Kotlin 프로그래밍 개념에 관해 알아보고 다양한 앱을 빌드합니다. Android Kotlin 기

developer.android.com


# 시작하며

저번글에서는 Room을 사용하기 위한 설정을 끝냈다면, 이번에는 기능적인 요소를 완성시켰다. 아직 코드랩에서 요구하는 100% 기능은 아니다.

 일반적으로 DB를 사용하는 작업과 네트워크를 사용하는 작업은 시간이 오래걸리기 때문에, 메인쓰레드에서 해당 작업을 진행하게 된다면, UI가 작동하지 않기 때문에 좋은 사용자 경험을 할 수 없음과 동시에 앱이 죽게 될 수 도 있다. 그럭히 때문에 다중 쓰레드 또는 코루틴을 이용해서 작업해야한다. 이번 챕터에서는 코루틴을 사용했다.

 

# DAO function을 suspend로 바꿔주기

@Dao
interface SleepDatabaseDao {

   @Insert
   suspend fun insert(night: SleepNight)

   @Update
   suspend fun update(night: SleepNight)

   @Query("SELECT * from daily_sleep_quality_table WHERE nightId = :key")
   suspend fun get(key: Long): SleepNight?

   @Query("DELETE FROM daily_sleep_quality_table")
   suspend fun clear()

   @Query("SELECT * FROM daily_sleep_quality_table ORDER BY nightId DESC LIMIT 1")
   suspend fun getTonight(): SleepNight?

   @Query("SELECT * FROM daily_sleep_quality_table ORDER BY nightId DESC")
   fun getAllNights(): LiveData<List<SleepNight>>
}

suspend는 코루틴 스코프 안에서 쓰이는 함수이다. getAllNights를 제외한 작업들은 코루틴 스코프 안에서 호출되기 때문에 suspend함수로 바꿔준다. 

특이하게 getAllNights함수는 suspend로 바꿔주지 않아도 됐다.

코드랩에서는 위와같은 설명이 있었다.  LiveData를 반환하는 쿼리문에 대해서는 이미 룸은 백그라운드 쓰레드에서 작업하고 있기 때문이라고 한다. 그렇기 때문에 DB가 update될 경우 즉 DB의 내용이 바뀔 경우 매번 getAll을 수행할 필요 없이, 디비가 최신상태를 유지하도록 해준다.

 

# start,stop구현하기 - ViewModel

start버튼을 누르면 현재시점을 시작으로하는 엔티티가 하나 생성되면서 DB에 저장 될 수 있도록 해야한다. 

private var tonight = MutableLiveData<SleepNight?>()

tonight변수를 통해서 현재의 night을 관찰할 수 있도록 한다. 

init {
    Log.d("ViewModel","SleepTrackerViewModel Created!")
    initializeTonight()
}
private fun initializeTonight() {
    viewModelScope.launch {
        tonight.value = getTonightFromDatabase()
    }
}
private suspend fun getTonightFromDatabase(): SleepNight?{
    var night = database.getTonight()
    if(night?.endTimeMilli != night?.startTimeMilli){
        night = null
    }
    return night
}

db에서 현재 night이 있는지를 알아낸다

 

이제 start버튼을 눌렀을때 새로운 SleepNight엔티티를 만들기 위한 이벤트처리를 해주도록 하자.

fun onStartTracking() {
    viewModelScope.launch {
        val newNight = SleepNight()
        insert(newNight)
        tonight.value = getTonightFromDatabase()
    }
}
private suspend fun insert(night: SleepNight) {
    database.insert(night)
}

코루틴을 이용해서 insert를 수행하도록 한다. 그리고 data-binding을 통해서 onClick메서드를 붙여주자. data-binding이 은근 편한거 같다.

android:onClick="@{() -> sleepTrackerViewModel.onStartTracking()}"

위와 같은 방법으로 onStop, onClear를 구현해준다.

fun onStopTracking() {
    viewModelScope.launch {
        val oldNight = tonight.value ?: return@launch
        oldNight.endTimeMilli = System.currentTimeMillis()
        update(oldNight)
    }
}

private suspend fun update(night:SleepNight) {
    database.update(night)
}

fun onClear() {
    viewModelScope.launch {
        clear()
        tonight.value = null
    }
}

private suspend fun clear(){
    database.clear()
}

 

# 모든 데이터 불러오기

 보통 리사이클러뷰를 사용해서 관리하겠지만, 지금 코드랩 순서로는 리사이클러뷰가 뒷 단원에 있어서 Transformaitions을 통해 받아온 모든 텍스트를 재조합해서 TextView에 한번에 그려주는 형태이다.

맨 처음 설명한 거와 같이 LiveData로 DB에서 반환을 하게 된다면, 따로 호출해줄 필요 없이 latest data로 업데이트 된다.

private val nights = database.getAllNights()

로 nights를 받아와 준다.

val nightsString = Transformations.map(nights) { nights ->
   formatNights(nights, application.resources)
}

제공해준 소스에서 nigths를 알맞게 정리해서 텍스트로 출력해준다.

android:text="@{sleepTrackerViewModel.nightsString}"

 

# 마치며

다음 코드랩에서는 평점 기능을 추가하는 기능을 구현한다.

저작자표시 (새창열림)

'•App > 안드로이드 with Kotlin' 카테고리의 다른 글

[안드로이드 코드랩/리사이클러뷰-1] 리사이클러 뷰 개념, 뷰 홀더 개념, 리사이클러뷰 만들기  (0) 2022.09.01
[안드로이드 코드랩/Room-3] 네비게이션을 통한 프래그먼트 전환시 인자 넘겨주기, 라이브데이터를 이용한 스낵바 구현, 뷰모델 및 라이브데이터 활용하기  (0) 2022.08.30
[안드로이드 코드랩/Room-1] 안드로이드 Room-DB만들기, Entity개념, DAO  (1) 2022.08.21
[안드로이드 코드랩/아키텍처-4] LiveData를 transformations사용하여 변환하기, 안드로이드 타이머 구현하기  (0) 2022.08.20
[안드로이드 코드랩/아키텍처-3] 데이터바인딩(data-binding) 을통한 뷰모델(viewModel), 라이브데이터(liveData) 결합  (0) 2022.08.19
    '•App/안드로이드 with Kotlin' 카테고리의 다른 글
    • [안드로이드 코드랩/리사이클러뷰-1] 리사이클러 뷰 개념, 뷰 홀더 개념, 리사이클러뷰 만들기
    • [안드로이드 코드랩/Room-3] 네비게이션을 통한 프래그먼트 전환시 인자 넘겨주기, 라이브데이터를 이용한 스낵바 구현, 뷰모델 및 라이브데이터 활용하기
    • [안드로이드 코드랩/Room-1] 안드로이드 Room-DB만들기, Entity개념, DAO
    • [안드로이드 코드랩/아키텍처-4] LiveData를 transformations사용하여 변환하기, 안드로이드 타이머 구현하기
    김호쭈
    김호쭈
    공부하고 정리하고 기록하기

    티스토리툴바