Phone

+48 884 880 380

AddressPL

Gliwice, 44-100

ul. Błogosławionego Czesława 13

AddressUK

Kemp House London, EC1V 2NX

152 - 160 City Road

Bird with cookies jar

This site uses cookies according to our privacy policy.

_Overview_Adding Android Architecture Components libraries_Entities annotations_Modelling entities_Relations_Writing DAOs_Creating a DB_Making queries_References

Android Architecture Components pt. 1 – Room

Android Architecture Components – a collection of libraries that helps to create applications. See how to configure the project, model entities and create DAOs

During Google I/O 2017, Google introduced the Android Architecture Components – a collection of libraries that helps developers create applications. It includes:

  • Room – SQLite object mapping library,
  • LiveData – data holder class that allows observing stored values,
  • ViewModel – configuration changes proof class to store data,
  • LifecycleObserver and LifecycleOwner – classes and interfaces to build lifecycle-aware components.

The next two parts of this article will include an introduction to the first library mentioned above – Room. Firstly, I’ll show you how to configure the project, model entities and create DAOs. In the next parts, we will bring together Room, RxJava and the rest of Android Architecture Components libraries in order to create a more flexible and maintainable app.


Overview

Room gives us a great alternative for standard, boilerplate SQLite operations. Room isn’t an ORM such as for example GreenDAO. It only provides an extra layer over SQLite. The main benefits of Room are:

  • compiler-time verification of SQL queries,
  • there’s no need to write boilerplate code to convert SQL queries and Java data objects.

While developing an app with Room, we need to implement all of three main components:

  • Entity,
  • Dao,
  • Database.

Communication between these three components is shown in the figure below:
Android Architecture Components - Room
Since we know what is Room and what does it consist of, it’s time to start creating our application. In this tutorial, we’ll try to create an application for saving our tasks and setting reminders to them. For every task, we are going to save some reminders with different priorities because there will be only one reminder notification per minute. So, after this short introduction – let’s start coding!


Adding Android Architecture Components libraries

Firstly, Room isn’t a part of the Android environment, so we need to add a dependency in gradle. Android Architecture Components are available on the Maven repository. To add it to your project, open your project build.gradle and paste the maven repository url:

Open app build.gradle and paste the latest* Room dependencies in dependencies section:

Now, synchronise your project and voilà – you can use Room.

  • Latest versions of all Android Architecture Components can be found here.

Entities annotations

Before we get started with modelling our entities, we need to know some useful annotations and their attributes.

  • @Entity – every model class with this annotation will have a mapping table in DB
    • foreignKeys – names of foreign keys
    • indices – list of indicates on the table
    • primaryKeys – names of entity primary keys
    • tableName
  • @PrimaryKey – as its name indicates, this annotation points the primary key of the entity:
    • autoGenerate – if set to true, then SQLite will be generating a unique id for the column
  • @ColumnInfo – allows specifying custom information about column
    • name
  • @Ignore – field will not be persisted by Room
  • @Embeded – nested fields can be referenced directly in the SQL queries.

Modelling entities

Now we can start coding. First of all, we need to model three classes – User, Task and Reminder as shown below:


Secondly, we can create the User class.

Let’s auto generate ids for each user. Set the autogenerate property to true. We also allow users to create one account per email For this, we’ve added @Index annotation and unique = true property.
Next, let’s create Task class.

We’ve got an autogenerated primary key. However, the most important is the declaration of @ForeignKey. It allows us to specify, what to do with all user tasks when the user deletes his account.
Now, we need to create Reminder class, which is very similar to Task, except the new annotation – @TypeConverters.  This annotation allows us to convert our custom data types to types which Room understands – all primitives and their boxed alternatives.

Converter class is just a simple class containing all converters. In our example, it’s Date to long and vice-versa.

Relations

Room does not allow to add object references between entities (for more see: https://developer.android.com/topic/libraries/architecture/room.html#no-object-references). A nice workaround is to create additional classes for resolving relations In our case these are user tasks and task reminders. We’ll use two annotations – @Embedded and @Relation.


As I mentioned before – @Embedded allows nested fields to be referenced directly in the SQL queries. @Relation describes relations between two columns. We have to specify the parent column name, entity column name and entity class. We don’t use @Entity annotation here. In the next step, we will use these classes to fetch data in our DAOs.


Writing DAOs

After hard work with entities, we can do something easier. Writing DAOs is really simple if we know the SQL syntax. I’ll show you only UserDao for brevity because Task and Reminder DAOs are very similar.

Every DAO interface must have @Dao annotations. For making queries we can use one of the bellows:

  • @Insert – inserts our entity class. We can insert single entity, array or list of longs passed by arguments. The method can return inserted ids as long, array or list of longs. This annotation provides one parameter:
    • onConflict – specifies what to do, if UNIQUE constraint failed (REPLACE, ROLLBACK, ABORT – default, FAIL, IGNORE).
  • @Update – updates entity, have onConflict as @Insert.
  • @Delete – deletes entity.
  • @Query – executes query passed by parameter. If we make SELECT, the method can return a single entity or array / list of entities.

We are now using relations class – UserAllTasks. Due to the fact that we specify relations, we can get user and all of his tasks in a single query.


Creating a DB

Finally, the last stage – creating a db (even easier than creating DAOs). All we need to do is to create an abstract class, which extends RoomDatabase and annotate this class by @Database. Furthermore, we have to pass which entities we want to use, specify the version of our db, create methods to return DAOs and build a database. All of these steps are shown below:

In the code above, I’ve implemented a simple singleton, but a better solution is to inject the database by Dagger or different DI library.
NOTE: Two marked methods are added temporarily. The fallbackToDestructiveMigration() to avoid writing migrations and the allowMainThreadQueries() to allow making queries in the main thread. Ignoring this method will cause an exception (if the query will be executed on the main thread). In the next part of this Android Architecture Components tutorial, I’ll show you how to write migrations and integrate Room with RxJava to avoid main thread queries.


Making queries

It’s just a simple example of how to use our db now:

The first part of articles about Android Architecture Components is a simple example of Room. Next time we’ll use Room, LiveData, RxJava and ViewModel at once to create a “robust, testable, and maintainable app”. If you have any questions feel free to ask in comments.
See the Android Data Binding tutorial to learn more about Android Architecture Components.

References

_