마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

Room 쓸때 DAO에서 반드시 LiveData를 반환해야하나요?

0 추천

필요없는 클래스 삭제하고 전혀 필요 없는 코드 삭제하기전에 동작 잘하는 것을 확인하고

클래스 삭제 및 코드를 삭제했는데 이후에 에러를 띄우면서 동작이 안돼다가

구글링해보니 DAO 클래스에서 suspend를 사용하던게 문제였던것 같은데요..

코드 및 에러입니다.

Workout

@Entity
data class Workout(
    @PrimaryKey(autoGenerate = true)
    val workoutId: Long = 0,
    val title: String = "",
    val memo: String = "",
)

 

WorkoutList

@Entity
data class WorkoutList(
    @PrimaryKey(autoGenerate = true)
    val id: Long = 0,
    val chest: List<String>,
    val back: List<String>,
    val leg: List<String>,
    val shoulder: List<String>,
    val biceps: List<String>,
    val triceps: List<String>,
    val abs: List<String>
)

 

DAO

@Dao
interface WorkoutListDao {
    @Query("SELECT * FROM WorkoutList")
    suspend fun getWorkoutList() : WorkoutList

    @Insert
    suspend fun insertWorkoutList(workoutList: WorkoutList)
}

 

Repository

class WorkoutListRepository(private val workoutListDao: WorkoutListDao) {
    suspend fun getWorkoutList(part: BodyPart) : List<String> {
        val partList = workoutListDao.getWorkoutList()

        return when(part) {
            is BodyPart.Chest -> partList.chest
            is BodyPart.Back -> partList.back
            is BodyPart.Leg -> partList.leg
            is BodyPart.Shoulder -> partList.shoulder
            is BodyPart.Biceps -> partList.biceps
            is BodyPart.Triceps -> partList.triceps
            is BodyPart.Abs -> partList.abs
        }
    }
}

 

ViewModel

class WorkoutListViewModel(application: Application) : AndroidViewModel(application){
    private var _list = MutableLiveData<List<String>>(arrayListOf())

    private val workoutDao = WorkoutListDatabase.getDatabase(application).workoutListDao()
    private val workoutListRepo = WorkoutListRepository(workoutDao)

    val list: LiveData<List<String>>
        get() = _list

    fun getList(part: BodyPart) {
        viewModelScope.launch(Dispatchers.IO) {
            val result = workoutListRepo.getWorkoutList(part)
            _list.postValue(result)
        }
    }
}

-------------------------------------

처음에는 Entity 클래스에서 

error: Cannot find setter for field.
    private final long workoutId = 0L;

이러한 에러를 띄웠습니다.

건드리지도 않은 코드의 에러가 왜 뜨는지 도저히 이해가 안갔지만 

android - Cannot find setter for field - using Kotlin with Room database - Stack Overflow

참고해서 val을 var로 변경했습니다.

그후 실행하니 

error: Not sure how to convert a Cursor to this method's return type (java.lang.Object).
    public abstract java.lang.Object getWorkoutList(@org.jetbrains.annotations.NotNull()

이러한 에러를 띄웠습니다.

검색 결과 

android - Room "Not sure how to convert a Cursor to this method's return type": which method? - Stack Overflow

여기서 suspend를 제거하라해서 했습니다. LiveData도 사용하라고 한것 같지만 이전에는 없어도 잘 동작되어서 일단 진행했습니다.

error: Type of the parameter must be a class annotated with @Entity or a collection/array of it.
    kotlin.coroutines.Continuation<? super kotlin.Unit> continuation);

그랬더니 이러한 에러를 띄웁니다..

아직 LiveData를 적용한 코드를 사용은 안해봤지만 그게 원인인가 싶구요.

기존에는 왜 LiveData를 사용하지 않고도 잘 되었을까요?

그리고 반드시 Room DAo를 사용할때 LiveData를 리턴한느 형식으로 사용해야하나요?

 

 

codeslave (3,580 포인트) 님이 6월 15일 질문

1개의 답변

0 추천
먼저 clean build 부터 해보시고 안되면 invalidate cache & restart 해 보세요. 코드가 문제가 없다면 빌드가 문제없이 될 겁니다.
LiveData를 리턴하든 않하든 문제가 없어야 할 것 같은데요
참,  DAO에 있는 함수에서 suspend를 제거해 보세요.
Room이 코드를 생성할 때 LiveData 리턴타입만 suspend를 지원하는 것 같아 보이네요. 혹시 room ktx 버전으로 되는지도 확인해 보세요
아래 라이브러리 개발자의 블로그도 참조하세요.
https://link.medium.com/HU4ZKZthSqb
spark (139,480 포인트) 님이 6월 15일 답변
spark님이 6월 15일 수정
...