sqlitekotlinandroid-jetpack-composeandroid-roomkotlin-coroutines

Returning a value from a Room database using Jetpack Compose


Hello and thank you for considering my question! I'm trying to query a database for a sum and display the total with a Jetpack Compose UI.

My DAO looks like this:

@Dao
interface FindDao {


    @Query("SELECT SUM(findAmount) FROM finds")
    suspend fun getFindTotal(): Double

}

My Repository looks like this:


class FindRepository (private val findDao: FindDao) {

 private val coroutineScope = CoroutineScope(Dispatchers.Main)


suspend fun getFindTotal():Double {
        return findDao.getFindTotal()

    }

    }

My Viewmodel looks like this:

class MainViewModel(application: Application): ViewModel() {

suspend fun getFindTotal(): Double {
        return repository.getFindTotal()
    }


}

And lastly my UI looks like:

@Composable
fun BottomBar(viewModel: MainViewModel) {
    val scope_Find_Total = rememberCoroutineScope()
    var retrievedFindTotal by remember { mutableStateOf<Double?>(null) }

    scope_Find_Total.launch {
        retrievedFindTotal = viewModel.getFindTotal()
    }


   Text("Find Total = $retrievedFindTotal")
}

So, this code works but I think I'm doing this wrong, I'm getting a warning "Calls to launch should happen inside a LaunchedEffect and not composition". Furthermore, I think maybe I shouldn't be launching co-routines from my UI? Not sure if I'm going about this properly?


Solution

  • You could do it in the ViewModel and expose a State<Double?> as a more idiomatic solution.

    ViewModel:

        private val _findTotal = mutableStateOf<Double?>(null)
        val findTotal: State<Double?> = _findTotal
    
        init {
            viewModelScope.launch {
                _findTotal.value = repository.getFindTotal()
            }
        }
    

    Composable:

    val findTotal by viewModel.findTotal
    
    Text("Find Total = $findTotal")