Chapters

Hide chapters

Saving Data on Android

Second Edition · Android 11 · Kotlin 1.5 · Android Studio 4.2

Using Firebase

Section 3: 11 chapters
Show chapters Hide chapters

9. The DAO Pattern
Written by Subhrajyoti Sen

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

In the previous chapter, you learned about different kinds of relations, such as one-to-one, one-to-many and many-to-many. You also learned how to create them using annotations.

In this chapter, you’ll learn how to retrieve, insert, delete and update data from your database using Database Access Objects (DAO).

Along the way, you will also learn:

  • What DAOs are and how they work.
  • How to create DAOs using Room annotations.
  • How to prepopulate the database using a provider class.
  • How to perform INSERT INTO queries using @Insert annotated methods.
  • How to perform DELETE FROM queries using @Deleteannotated methods.
  • How to use @Query to read data from the database.

Ready? Dive in!

Getting started

Download the starter project attached to this chapter and open it using Android Studio 4.2 or above. Once Gradle finishes building your project, take some time to familiarize yourself with the code. If you have been following along, to this point, you should already be familiar with the project since it is the same as the final project from the last chapter. If you are just getting started, here is a quick recap of the code:

  • The data package contains two packages: db and model. The db package contains the QuestionDatabase class, which defines your Room database. The model package contains your entities: Question and Answer.
  • The view package contains all your activities: SplashActivity, MainActivity, QuestionActivity, and ResultActivity.

Now, build and run the app to verify that everything is working properly.

The Main screen.
The Main screen.

Cool! Now you are ready to start creating some Database Access Objects to manipulate the data.

Using DAOs to query your data

Database Access Objects are commonly known as DAOs. DAOs are objects that provide access to your app’s data, and they are what make Room so powerful since they abstract most of the complexity of communicating to the actual database. Using DAOs instead of query builders or direct queries makes it very easy to interact with your database. You avoid all the hardship of debugging query builders, if something breaks, and we all know how tricky SQL can be! They also provide a better separation of concerns to create a more structured application and improve its testability.

@Dao
interface QuizDao {
}
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(question: Question)

@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(answer: Answer)
@Query("DELETE FROM question")
fun clearQuestions()
@Delete
fun deleteQuestion(question: Question)
@Query("SELECT * FROM question ORDER BY question_id") // 1
fun getAllQuestions(): List<Question>

@Transaction // 2
@Query("SELECT * FROM question") // 3
fun getQuestionAndAllAnswers(): List<QuestionAndAllAnswers>
abstract fun quizDao(): QuizDao
@Database(
    entities = [(Question::class), (Answer::class)],
    version = 1
)
abstract class QuizDatabase : RoomDatabase() {

    abstract fun quizDao(): QuizDao
}

Creating a provider class

Now that your DAO methods are ready, you’ll create a provider class, that you will need later on, to prepopulate your database. Create a new class under the data package, name it QuestionInfoProvider and add the following method:

private fun initQuestionList(): MutableList<Question> {
  val questions = mutableListOf<Question>()
  questions.add(
      Question(
          1,
          "Which of the following languages is not commonly used to develop Android Apps")
  )
  questions.add(
      Question(
          2,
          "What is the meaning of life?")
  )
  return questions
}
private fun initAnswersList(): MutableList<Answer> {
  val answers = mutableListOf<Answer>()
  answers.add(Answer(
      1,
      1,
      true,
      "Java"
  ))
  answers.add(Answer(
      2,
      1,
      false,
      "Kotlin"
  ))
  answers.add(Answer(
      3,
      1,
      false,
      "Ruby"
  ))
  answers.add(Answer(
      4,
      2,
      true,
      "42"
  ))
  answers.add(Answer(
      5,
      2,
      false,
      "35"
  ))
  answers.add(Answer(
      6,
      2,
      false,
      "7"
  ))
  return answers
}
val questionList = initQuestionList()
val answerList = initAnswersList()
object QuestionInfoProvider { ...}
Verifying that the app is working fine.
Feyebgezj fpoq wki att ug linyeml xaqa.

Testing your database

Although your app’s UI isn’t working yet, you can still interact with your database by performing some tests such as adding or deleting questions to verify its functionality.

The androidTest package.
Kke oyssoewFacd huzzaco.

@RunWith(AndroidJUnit4::class)
class QuizDaoTest { // 1
  @Rule
  @JvmField
  val rule: TestRule = InstantTaskExecutorRule() // 2

  private lateinit var database: QuizDatabase // 3
  private lateinit var quizDao: QuizDao // 4
}
@Before
fun setUp() {
  val context = InstrumentationRegistry.getInstrumentation().context // 1
  try {
    database = Room.inMemoryDatabaseBuilder(
        context, 
        QuizDatabase::class.java) //2
      .allowMainThreadQueries() //3
      .build()
  } catch (e: Exception) {
    Log.i(this.javaClass.simpleName, e.message ?: "") //4
  }
  quizDao = database.quizDao() //5
}
@Test
fun testInsertQuestion() {
  // 1
  val previousNumberOfQuestions = quizDao.getAllQuestions().size
  //2
  val question = Question(1, "What is your name?")
  quizDao.insert(question)
  //3
  val newNumberOfQuestions = quizDao.getAllQuestions().size
  //4 
  val changeInQuestions = newNumberOfQuestions - previousNumberOfQuestions
  // 5
  Assert.assertEquals(1, changeInQuestions)
}
@Test
fun testClearQuestions() {
  for (question in QuestionInfoProvider.questionList) {
    quizDao.insert(question)
  }
  Assert.assertTrue(quizDao.getAllQuestions().isNotEmpty())
  Log.d("testData", quizDao.getAllQuestions().toString())
  quizDao.clearQuestions()
  Assert.assertTrue(quizDao.getAllQuestions().isEmpty())
}
@After
fun tearDown() {
  database.close()
}
Running the Instrumenttion Test.
Javnejv sva Idwcrovakfmeuv Donr.

Key points

Where to go from here?

You now know how to create DAOs to interact with your database. You can download the final project by opening the attachment on this chapter, and if you want to learn more about DAOs in Room, you can explore the following resources:

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2024 Kodeco Inc.

You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now