Data Persistence With Room

Learn how to persist data in your Android app using the Room SQLite wrapper from Google, and how to test your database using Espresso. By Lance Gleason.

4.2 (20) · 2 Reviews

Download materials
Save for later
Share

Many apps need to deal with persisting data. Perhaps you have an app that stores your favorite pet photos, a social networking app for cat lovers, or an app to maintain lists of things that you might need for your next vacation.

Android provides a number of options, including:

  • Shared Preferences: For storing primitive data in key-value pairs.
  • Internal Storage: For storing private data on device storage.
  • External Storage: For storing public data on shared external storage.
  • SQLite Databases: For storing structured data in a private database.

When your data is structured, and you need to be able to do things such as searching for records in that data, a SQLite database is often the best choice. This is where Room comes in. Room is a SQLite wrapper library from Google that removes much of the boilerplate code you need to interact with SQLite, and also adds compile-time checking of your SQL queries.

In this tutorial, you will build an application that creates a generic list that could be used as a shopping, to-do or packing list. In this tutorial you will learn:

  • The basics of setting up a Room database.
  • How to use a DAO to Create and Read data.
  • The basics of unit testing your persistence layer.
  • How to hook up your database to an Android UI.

Note: This tutorial assumes that you have some experience developing Android applications. A few points to keep in mind:

  • You will be using the Android RecyclerView to display lists. If you’ve never used them or need a refresher, the Android RecyclerView Tutorial with Kotlin is a great place to start.
  • This tutorial utilizes Data Binding and Binding Adapters. Again, if you have never used these or need a refresher, you should take a look at the data binding documentation from the Android project pages.
  • The code snippets in this tutorial do not include the needed import statements. Use the key combination Option-Return on Mac Alt-Enter on PC to resolve any missing dependencies as you work through your project.
  • Introduction to Android Data Persistence

    Classes, Tables, Rows and Instances

    To understand Room, it is helpful to understand the sum of its parts, so let’s start with a simple example of storing the names, addresses and phone numbers of a few people.

    When you are developing applications using an object-oriented programming language like Kotlin, you use classes to represent the data that you are storing. In our example you could create a class called Person, with the following attributes:

    • name
    • address
    • phoneNumber

    For each person you’d then create an instance of a Person, with unique data for that individual.

    With a SQL relational database, you would model the Person class as a table. Each instance of that person would be a row in that table. In order to store and retrieve this data, SQL commands need to be be issued to the database, telling it to retrieve and store the data.

    For example, to store a record in a table you might use a command like:

    INSERT INTO Persons (Name, Address, TelephoneNumber)
    VALUES ('Grumpy Cat', '1 Tuna Way, Los Angeles CA', '310-867-5309');
    

    In the early days of Android, if you had a Person object that you wanted to store in the SQLite database, you would have had to create glue code that would turn objects into to SQL and SQL into objects.

    Glue code

    ORMs and Android

    Long before the days of Android, developers in other object-oriented languages started using a class of tool called an ORM to solve this problem. ORM stands for Object Relational Mapper. The best way to think of it is as a tool designed to automatically generate glue code to map between your object instances and rows in your database.

    When Android came on the scene, no ORM existed for the Android environment. Over the years, open-source ORM frameworks emerged, including DBFlow, GreenDAO, OrmLite, SugarORM and Active Android. While these solutions have helped to solve the basic problem of reducing glue code, the developer community has never really gravitated towards one (or two) common solutions. This has led to significant fragmentation and limitations in many of these frameworks, especially with more complex application lifecycles.

    Google’s Android Architecture Components and Room

    Beyond data persistence, a number of patterns have emerged within the Android development community to deal with things such as maintaining state during application lifecycle changes, callbacks, separating application concerns, view models for MVVM applications, etc. Luckily, in 2017, Google took some of the best practices from the community and created a framework called the Android Architecture Components. Included in this framework was a new ORM called Room. With Room you have an ORM to generate your glue code with the backing of the creators of Android.

    Room as Glue

    Getting Started With Room

    To kick things off, start by downloading the materials for this tutorial (you can find the link at the top or bottom of this tutorial), unzip it, and start Android Studio 3.1.1 or later.

    In the Welcome to Android Studio dialog, select Import project (Eclipse ADT, Gradle, etc.).

    Welcome to Android Studio

    Choose the ListMaster directory of the starter project, and click Open.

    Import project

    If you see a message to update the project’s Gradle plugin since you’re using a later version of Android Studio, go ahead and choose “Update”.

    Check out the project for the List Master app and you will see two packages for list categories and list items. You’ll be working only in the first package in this tutorial.

    Build and run the application and your app will look like this:

    Starter app

    Under the Gradle Scripts part of your project you’ll see a build.gradle file with a (Module:app) notation. Double-click to open it and add the following dependencies that add Room to your project.

    implementation "android.arch.persistence.room:runtime:1.0.0"
    kapt "android.arch.persistence.room:compiler:1.0.0"
    annotationProcessor "android.arch.persistence.room:compiler:1.0.0"
    androidTestImplementation "android.arch.persistence.room:testing:1.0.0"
    androidTestImplementation "android.arch.core:core-testing:1.1.0"
    

    Go ahead and sync Gradle files once you’ve made the change.

    You now have your Room dependencies. Next, you will need to add the following things to use Room in your app:

    • Entity: An entity represents the data model that you are mapping to a table in your database.
    • DAO: short for Data Access Object, an object with methods used to access the database.
    • Database: A database holder that serves as the main access point for the connection to your database.