Coroutines With Room Persistence Library

In this tutorial, you’ll learn how to use coroutines with the Room persistence library to allow for asynchronous database operations. By Kyle Jablonski.

4.5 (11) · 2 Reviews

Download materials
Save for later
Share
You are currently viewing page 3 of 3 of this article. Click here to view the first page.

Updating a Player

To update a tennis player, use the same approach you took in the previous steps. There will again be a series of steps to complete the feature, but it won’t be so difficult this time. You already laid the groundwork after all.

Adding Update to the Dao

To begin, open the PlayerDoa.kt file and add the updatePlayer() as shown below:

@Update
suspend fun updatePlayer(player: Player)

Here, you annotate with @Update to tell Room that updatePlayer() DAO method will perform update operations. The suspend keyword in the method signature lets Room know this DAO method will suspend its execution.

Adding Update to the Repository

Next, open the PlayerRespository.kt file and add the following code:

suspend fun updatePlayer(player: Player) {
  playerDao.updatePlayer(player)
}

Here you wrapped the DAO’s functionality to update a Player with another suspension function.

Note: This step is necessary because suspending functions can only execute from other suspending functions or from within a coroutine.

Adding Update to the ViewModel

Time to update the DetailViewModel.kt file to run the repository’s updatePlayer(player: Player) within a coroutine. First, add the following method to the end of DetailViewModel.kt file:

// 1
fun updatePlayer(player: Player) = viewModelScope.launch {
  // 2
  repository.updatePlayer(player)
}
    Here, you added a new method to update the Player. This method uses
  1. viewModelScope to call launch, a coroutine builder method
  2. This, in turn, calls updatePlayer(player: Player) within a coroutine.

Adding Update to the UI

Next up, you will setup the MenuItem in the Toolbar to update the selection of favorite player in the database. For simplicity, you will make changes only in the setupFavoriteToggle() function.

Open the DetailsFragment.kt file and replace the TODO in setupFavoriteToggle(checkBox: CheckBox, player : Player) with the following:

// 1
checkBox.setOnCheckedChangeListener { _, b ->
  // 2
  player.favorite = b
  // 3
  detailViewModel.updatePlayer(player)
}
// 4
checkBox.isChecked = player.favorite

Here you are:

  1. Attaching OnCheckedChangeListener to the checkbox star MenuItem.
  2. Assigning the player-favorite property to the checkbox checked value.
  3. Calling updatePlayer(player) from ViewModel.
  4. Handling the initial value of checkBox.isChecked.

Now, you need to call this setupFavoriteToggle method from the observer up in onViewCreated().

Add the call to setupFavoriteToggle, just above displayPlayer() in the observer definition as shown below:

detailViewModel.getPlayer(playerListItem).observe(this, Observer {
  this.player = it

  setupFavoriteToggle(checkbox, it) // called the method here 

  displayPlayer()
})

Here, you’re calling the method that sets up the checkbox toggle for favorites.

Great Job! Now when you navigate away from the DetailsFragment you will see a filled-in star next to the Player within the list and when you navigate back to DetailsFragment the star menu item will highlight as well. Best of all, this is all happening by calling to update the player within the database using the DAO’s suspending function and the ViewModelScope‘s launch method to run the operation in a coroutine.

Build and run the application to observe the new behavior. You can now favorite your favorite players.

favorite a tennis player

Deleting a Player

Users may also want to remove players from the application. In this step, you’ll add a delete-player feature for just such an occasion.

Adding Delete to the DAO

To begin, open the PlayerDoa.kt file and add the deletePlayer() method call:

@Delete
suspend fun deletePlayer(player: Player)

This should look familiar. You’ve added another suspending function to the DAO and provided @Delete annotation so that Room knows this method will perform delete operations.

Adding Delete to the Repository

Now, it’s time to update the repository. Open the PlayerRepository.kt file and add the following code:

suspend fun deletePlayer(player: Player) {
  playerDao.deletePlayer(player)
}

Here, you added another suspending function that uses PlayerDao to call the deletePlayer() method from the previous step.

Adding Delete to the ViewModel

You’ll have to update DetailsViewModel again to call the deletePlayer() method from repository. Open the DetailsViewModel.kt file and add the following method:

// 1
fun deletePlayer(player: Player) = viewModelScope.launch {
  // 2
  repository.deletePlayer(player)
}

Here, you’re doing much the same as the update method call from the previous feature implementation. You use viewModelScope to call launch and run the operation in a coroutine.

Wow, you are becoming a pro at this!

Adding Delete to the UI

In this last step, you’ll add delete behavior to the UI. Open the DetailsFragment.kt file one more time and add the following code inside deleteCurrentPlayer() replacing the TODO:

detailViewModel.deletePlayer(player)
dismiss()

Here, you invoked deletePlayer(player) on the detailViewModel and dismissed DetailsFragment.

Build and run the application to observe the new behavior. You can now delete any players you’d like.

deleting a player

Where to Go From Here?

Great Job! You’re now a Suspension-Function-Room-Database-Storing Pro! If you had any difficulty following along, no worries. Just import the TennisPlayers-final version of the application and compare your code to it.

If you enjoyed working with LiveData, you may discover you enjoy the new Flow addition from the release of 2.2. For more information on Flow, check out the developer’s release notes.

If you’re looking for Room or Coroutine content, read Room DB: Advanced Data Persistence or Kotlin Coroutines Tutorial for Android: Advanced to learn more.

Thank you for reading! If you have any questions or comments, please join the forum discussion below!