I have a Jetpack Compose Picture App where the user views Cached Photos from ROOM Database. The database has a isFavorite
column which stores Booleans and is updated when the user clicks to like the photo.
This is my dao
@Query("SELECT * FROM astrophotoentity")
suspend fun getSavedAstroPhotos(): Flow<List<AstroPhotoEntity>>
@Query("UPDATE astrophotoentity SET isFavorite =:isFavorite WHERE id=:id")
suspend fun updateIsFavoriteStatus(id: String,isFavorite:Boolean)
This is my Repository code
override suspend fun updateIsFavoriteStatus(photo: AstroPhoto, isFavorite:Boolean) {
dao.updateIsFavoriteStatus(photo.date,isFavorite)
}
I am using a use case class for clean architecture.
class UpdateIsFavoriteStatusUseCase (private val repository: AstroRepository) {
suspend operator fun invoke(photo: AstroPhoto, isFavorite:Boolean){
repository.updateIsFavoriteStatus(photo, isFavorite)
}
}
I also use a simple data class to hold state for the ViewModel.
data class PhotoState(
val astroPhotos: List<AstroPhoto> = emptyList(),
val isPhotosListLoading: Boolean = false,
val errorMessage: String? = null)
This is the ViewModel which initializes the Photo State list to a list fetched from the DB. I use mutableStateOf()
to hold the photo objects list. Here I update isFavorite column in the database depending on the passed event.
@HiltViewModel
class OverviewViewModel @Inject constructor(
private val useCaseContainer: UseCaseContainer
) : ViewModel() {
var state by mutableStateOf(PhotoState())
private set
init {
//set the state to the retrieved list of photo objects
... getPhotosListFromDb()
}
fun onEvent(event: OverviewEvent) { ....
is OverviewEvent.OnMarkFavorite -> { ....
useCaseContainer.updateIsFavoriteStatus(event.photo, event.isFavorite)}
is OverviewEvent.OnRemoveFromFavorites -> { ....
useCaseContainer.updateIsFavoriteStatus(event.photo, event.isFavorite)}
I pass the Photos list to the below composable.
@Composable
fun AstroPhotoComposable(
photo: AstroPhoto,
onMarkAsFavorite: () -> Unit,
onRemovePhoto: () -> Unit = {}
) {
//retrieve the isFavorite state using photo.isFavorite and cache it
var isFavorite by remember{ mutableStateOf(photo.isFavorite) ... }
The issue I am facing is that when the photo changes from isFavorite/!isFavorite
the state is not reflecting live on the UI.
I have read somewhere about cold and hot kotlin flows but I'm yet to wrap my head around this. I also tried to replace mutableStateOf
with MutableStateFlow
but the state is not updating on Database Changes.
Basically, I am looking to observe for database changes and get an up-to-date state similar to LiveData
.
Any help is appreciated.
CodePudding user response:
Have you ever tried updating the whole entity?
@Update
suspend fun update(myEntity: myEntity): Int
And in my opinion it has to be without suspend
@Query("SELECT * FROM astrophotoentity")
fun getSavedAstroPhotos(): Flow<List<AstroPhotoEntity>>
I'd do it like that.
fun getSavedAstroPhotos() = dao.getSavedAstroPhotos().map{ it.toPhotoState() }
And collect it in view model
init {
viewModelScope.launch {
getSavedAstroPhotos().collect{
state = it
}
}
}
Perhabs it helps you link