In this section, you’ll add the remaining CRUD operations - update and delete. These new functions will be added to your DAO and repository to update and delete Room database notes.
Open the NotesDao interface in the data/local package, and add two new functions to update and delete notes:
@Update
suspend fun update(note: NoteEntity)
@Delete
suspend fun delete(note: NoteEntity)
Add your dependencies as Android Studio prompts you.
Here, you use the @Update and @Delete annotations to define the functions that update and delete notes, respectively. Next, navigate to the repository package and open the NotesRepository.kt file. Add the following functions to your interface:
suspend fun update(noteEntity: NoteEntity)
suspend fun delete(noteEntity: NoteEntity)
This causes your NotesRepositoryImpl to throw an error because it doesn’t implement these two functions. You’ll fix this in the NotesRepository.kt file. Add the following implementations in the NotesRepositoryImpl class:
override suspend fun update(noteEntity: NoteEntity) {
withContext(ioDispatcher) {
notesDao.update(noteEntity)
}
}
override suspend fun delete(noteEntity: NoteEntity) {
withContext(ioDispatcher) {
notesDao.delete(noteEntity)
}
}
The update and delete functions use the withContext function to switch to the I/O dispatcher. They then call the corresponding functions in the NotesDao interface to update and delete notes. Your DAO and repository are now ready to update and delete notes from the Room database. In the next few steps, you’ll update the UI layer to call these functions and support updating and deleting notes that are saved in the Room database.’
Start by navigating to ui/state/. Open CreateNoteState.kt. Add the following code to the end of the sealed interface, CreateNoteEvents:
data object UpdateNote : CreateNoteEvents
You’ll use the UpdateNote event to update a note in the Room database. Navigate to ui/viewmodels/. Open your MainViewModel class. The when expression in the handleCreateNoteEvents function should now have an error. The error occurs because you’ve not handled all the cases. Below the NoteLocationChanged case, add the following case to handle the UpdateNote event:
CreateNoteEvents.UpdateNote -> {
if (createNoteState.value.isValid()) {
viewModelScope.launch {
val noteEntity = NoteEntity(
id = currentNote.value?.id ?: 0,
title = createNoteState.value.title ?: "",
description = createNoteState.value.description ?: "",
priority = createNoteState.value.priority ?: "",
timestamp = System.currentTimeMillis(),
noteLocation = createNoteState.value.noteLocation ?: ""
)
notesRepository.update(noteEntity)
}
}
}
In the code above, you check if the createNoteState is valid and then create a new NoteEntity object with the updated values. Notice that you use the currentNote value to get the ID of the note that you want to update unlike others. This is because you want to update the note with the same ID and not create a new note since the note of your ID will be autogenerated if you don’t provide one. You then call the update function in the notesRepository to update the note in the Room database. The currentNote is highlighted as an error because you’ve not yet defined it. To fix this, add the following code at the top of your MainViewModel class:
private val _currentNote = MutableStateFlow<NoteEntity?>(null)
val currentNote = _currentNote.asStateFlow()
Here, you define a new MutableStateFlow variable called _currentNote that holds the current note that you want to update. You then expose this variable as an immutable StateFlow called currentNote. Now, you need to create a function that updates the current note. Add the following function to your MainViewModel class below your fetchNotes() function:
fun updateNoteWithPreviousDetails(noteEntity: NoteEntity) {
_currentNote.update {
noteEntity
}
_createNoteState.update {
it.copy(
title = noteEntity.title,
description = noteEntity.description,
priority = noteEntity.priority,
noteLocation = noteEntity.noteLocation
)
}
}
The function above updates the _currentNote and _createNoteState variables. The update edits the detail member of your selected note. You update the state so that the UI displays the details of the note that you want to update.
Now, you need to update the EditNoteScreen composable. The composable needs to call the updateNoteWithPreviousDetails and handleCreateNoteEvents functions. The call is made with different events, like the create note composable. Navigate to ui/views/. Open the EditNoteScreen.kt file and replace the // TODO: update state with previous note details with:
viewModel.updateNoteWithPreviousDetails(it)
Here, you call the updateNoteWithPreviousDetails function in the viewModel with the note that you want to update. This updates the state of the currentNote and createNoteState variables with the details of the note that you want to update. Next, replace the // TODO: add update note screen content with:
UpdateNoteScreenContent(
createNoteState = createNoteState,
onTitleChange = { title ->
viewModel.handleCreateNoteEvents(CreateNoteEvents.TitleChanged(title))
},
onDescriptionChange = { description ->
viewModel.handleCreateNoteEvents(CreateNoteEvents.DescriptionChanged(description))
},
onPriorityChange = { priority ->
viewModel.handleCreateNoteEvents(CreateNoteEvents.PriorityChanged(priority))
},
onUpdateNote = {
viewModel.handleCreateNoteEvents(CreateNoteEvents.UpdateNote)
navigateToHome()
},
onNoteLocationChange = { noteLocation ->
viewModel.handleCreateNoteEvents(CreateNoteEvents.NoteLocationChanged(noteLocation))
}
)
Here, you call the UpdateNoteScreenContent composable with the createNoteState. Notice that the various event handlers are similar to the ones for creating a note. The rest of the functionality for calling the editNote callback has already been done for you. Remember to import your dependencies.
Now, build and run the app. You can click any of the notes that you stored in Room Database. Click the Edit icon at the top. It takes you to the Edit Note screen with the details of the note you clicked. You can now update the note details and click the Update Note button to update the note in the Room database. Your note will be updated, and you’ll be taken back to the Home screen. The note you updated will now reflect the new details you entered.
Now that you can update notes, you’ll add the functionality to delete notes from the Room database. Head over to your MainViewModel class and add this function below updateNoteWithPreviousDetails function:
fun delete(noteEntity: NoteEntity) {
viewModelScope.launch {
notesRepository.delete(noteEntity)
}
}
This function calls the delete function in the notesRepository to delete notes from the Room database. Next, navigate to ui/views/. Open NoteDetailsScreen composable and replace the // TODO: Implement delete functionality with:
viewModel.delete(it)
navigateBack()
Here, you call the delete function in the viewModel with the note that you want to delete. This deletes the note from the Room database and then navigates back to the Home screen.
Build and run the app. You can now click any of the notes that you stored in the Room database. Click the Delete icon at the top and the note will be deleted from the Room database. You’ll be taken back to the Home screen and the note you deleted will no longer be displayed. You’ve now added the functionality to update and delete notes from the Room database.