Instruction

Instruction

This section covers CRUD operations and how to perform them in Room databases. You’ll learn to create, read, update, and delete data.

Understanding CRUD Operations

CRUD stands for Create, Read, Update, and Delete. These are the four basic operations that you can perform on a database. You use these main operations to interact with the data in a database.

Exploring CRUD Operations in Room Databases

In Room database, you use Data Access Objects (DAOs) to define the operations that you want to perform on the database. You can use these operations to create, read, update, and delete data in the database. You have already learned about DAOs in the previous section.

For better separation of concerns, you can create a repository that interacts with the DAOs and exposes the data to the rest of the app. The repository handles the data operations and abstracts the data sources from the rest of the app. This is called the repository pattern. At times, your app can have multiple data sources, such as a network and a local database. The repository pattern helps you manage these data sources and provides a clean way for the rest of the app to interact with the data. The repository maintains the source of truth for the data and decides where to fetch the data from. The rest of your app won’t know where the data is coming from, whether it’s from the network or the local database.

For example, with the Notes app, you can have the following:

interface NotesRepository {
  suspend fun saveNote(noteEntity: NoteEntity)
  fun getNotes(): Flow<List<NoteEntity>>
  suspend fun update(noteEntity: NoteEntity)
  suspend fun delete(noteEntity: NoteEntity)
}

In the code above, you have a NotesRepository interface that defines the operations that you can perform on your notes database. The saveNote function is a suspend function that takes a NoteEntity object as a parameter. The getNotes function returns a Flow of List<NoteEntity> that you can use to observe the notes in the database. The update and delete functions are suspend functions. These functions update and delete notes from the database, respectively. Having this as an interface allows you to create different implementations of the repository and makes it easier to test your code.

A sample implementation of the NotesRepository interface is shown below:

class NotesRepositoryImpl(
  private val ioDispatcher: CoroutineDispatcher,
  private val notesDao: NotesDao
): NotesRepository {
  override suspend fun saveNote(noteEntity: NoteEntity) {
    withContext(ioDispatcher) {
      notesDao.insert(noteEntity)
    }
  }

  override fun getNotes(): Flow<List<NoteEntity>> {
    return notesDao.getNotes()
  }

  override suspend fun update(noteEntity: NoteEntity) {
    withContext(ioDispatcher) {
      notesDao.update(noteEntity)
    }
  }

  override suspend fun delete(noteEntity: NoteEntity) {
    withContext(ioDispatcher) {
      notesDao.delete(noteEntity)
    }
  }
}

To explain the code above:

  • The NotesRepositoryImpl class implements the NotesRepository interface. In the constructor, you have two parameters, ioDispatcher and notesDao. The ioDispatcher is a CoroutineDispatcher that you’ll use to run the database operations on a background thread. The notesDao is an instance of the NotesDao class that you’ll use to interact with the database.
  • The saveNote function is a suspend function that takes a NoteEntity object as a parameter. Inside the function, you call the insert function on the notesDao object to insert the note into the database.
  • The getNotes function returns a Flow of List<NoteEntity>. Inside the function, you call the getNotes function on the notesDao object to get all the notes from the database.
  • The update and delete functions are suspend functions that update and delete notes from the database, respectively. Inside the functions, you call the corresponding functions on the notesDao object to update and delete the notes.

Having this simplifies the way you interact with the database. Other layers that need to perform any of the CRUD operations can call the corresponding functions in the repository. This way, you can easily switch the data source without affecting the rest of the app.

You can use the NotesRepository in your ViewModels. You can also use other classes depending on your architecture. These classes perform CRUD operations on the database.

See forum comments
Download course materials from Github
Previous: Introduction Next: Demo: Create & Read Notes from Room Database