Android Jetpack Architecture Components: Getting Started
In this tutorial, you will learn how to create a contacts app using Architecture Components from Android Jetpack like Room, LiveData and ViewModel. By Zahidur Rahman Faisal.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Android Jetpack Architecture Components: Getting Started
35 mins
- Getting Started
- Adding Dependencies for Architecture Components
- Creating ROOM for Your Contacts
- Creating Entities
- Creating a Data Access Object (DAO)
- Creating the Database
- Pre-populating a Room Database
- Live Updates With LiveData
- Introducing ViewModel
- Mastering ViewModel and LiveData
- Implementing Search
- Mapping With LiveData Transformations
- ViewModels Everywhere
- Architecture Layers
- Exploring Navigation Components
- Preparing for Navigation
- Navigating to the Next Fragment
- Navigation With Additional Data
- Where to Go From Here?
Developing Android apps is just like playing video games — it’s challenging and rewarding at the same time! While enjoying your journey through the Android world, you must have faced many obstacles and wished for some kind of Jetpack to jump through those obstacles, or that you had a nitro boost to kickstart your development engine for the sprint…
Google heard you – now Android literally offers you a Jetpack!
Android Jetpack is a set of libraries that helps you to deal with the challenges you eventually face as a Android Developer — writing boilerplate code, managing activity lifecycles, surviving configuration changes or preventing memory leaks.
In this tutorial, you’ll create a contact list app called iMet using Android Jetpack, which stores contact information about the people you have met.
In the process, you’ll learn:
- To create a Room database to store and retrieve data.
- To use ViewModel to isolate use cases from the View.
- To view data and observe changes using LiveData.
- To simplify navigation and data passing within the app using Navigation Components.
- And More!
Getting Started
Get started by downloading and installing the preview release of Android Studio from here.
Download the zip file containing the starter project for this tutorial using the Download materials button at the top or bottom of this tutorial.
Now, on macOS launch Android Studio 3.3 Preview from your Applications folder as shown above and select Open an existing Android Studio project to import the starter project that you just downloaded. On Linux and Windows, follow the steps for your OS to start Android Studio 3.3 Preview and open the starter project.
Build and run using keyboard shortcut Shift + F10 (or Control + R if you’re on macOS). If you see a list of awesome people like following, you’re all set to dive in!
Start exploring the PeopleRepository class inside the data package in the starter project. PeopleRepository is the gatekeeper of the data layer in your app. It holds all data regarding People and provides information to different segments in the app — for example: PeoplesListFragment.
You must be thinking, “What’s the source of data for PeopleRepository?!”
Well, assume PeopleInfoProvider, inside the net package within data, is your helper class that fetches People information from some web-service and stores it in PeopleRepository.
But how about adding the People that you’ve just met today into the PeopleRepository so that you can contact them later?
To achieve that, you need to update PeopleRepository to store data from all your sources (local or remote), making it a single source of truth for managing the People information.
So, here’s your first challenge – adding persistence!
Adding Dependencies for Architecture Components
Jetpack depends on a few external libraries, so you need to add those dependencies first. Open the build.gradle file from your app module and append the following lines just above the closing brackets of the dependencies section:
// 1: Room Components
def roomVersion = "1.1.1"
implementation "android.arch.persistence.room:runtime:$roomVersion"
kapt "android.arch.persistence.room:compiler:$roomVersion"
// 2: Lifecycle Components
def lifecycleVersion = "1.1.1"
implementation "android.arch.lifecycle:extensions:$lifecycleVersion"
// 3: Navigation Components
def navigationVersion = "1.0.0-alpha04"
implementation "android.arch.navigation:navigation-fragment-ktx:$navigationVersion"
implementation "android.arch.navigation:navigation-ui-ktx:$navigationVersion"
These dependencies provide components with the following capabilities:
- Room Components: Add local persistence in your app. Room is an object-mapping library wrapping SQLite to make your database management concise and painless.
- Lifecycle Components: Lift the responsibility of managing your app’s lifecycle with ease. They add lifecycle-aware components like ViewModel and LiveData that allows you to forget about writing code for handling configuration changes or loading data into your UI when there’s an update.
- Navigation Components: Add helper classes like NavController to simplify navigation and passing of data throughout your app.
Creating ROOM for Your Contacts
To pass your first challenge, persistence, you need to implement three major components from Room:
- Entity: A model class that represents a table in a Room database.
- Data Access Object (DAO): A helper class to access and query the database.
- Database: An abstract class that directly extends RoomDatabase. It’s main responsibility is creating the database and exposing entities through Data Access Objects (DAO).
Creating Entities
Start with the simplest component first. You already have a People class inside the model which is nested in the data package; now, modify it to match the following to declare it as an Entity for your Room database:
package com.raywenderlich.android.imet.data.model
import android.arch.persistence.room.Entity
import android.arch.persistence.room.PrimaryKey
@Entity
data class People(
var name: String = "",
var metAt: String = "",
var contact: String = "",
var email: String = "",
var facebook: String = "",
var twitter: String = "",
@PrimaryKey(autoGenerate = true) var id: Int = 0
)
Here, you’re using two annotations from Room:
- @Entity: Declares that you’re going to use this model as an Entity.
-
@PrimaryKey: Defines
id
as the Primary Key for the Entity. AddingautoGenerate = true
ensuresid
will be automatically generated whenever you create a new record in the database with this Entity.
Piece of cake! Moving on to the next one…
Creating a Data Access Object (DAO)
A DAO is basically an interface to access required data from your database. It has two sole purposes:
- It saves you from writing direct queries, which are more error-prone and harder to debug.
- It isolates query logic from database creation and migration code for better manageability.
Create a new package for the DAO and Database classes. Right-click on the data package, then select New ▸ Package.
Name it db inside the New Package dialog and click OK.
Create a new Kotlin Interface inside the db package and name it PeopleDao.
As you’re going to use this class for database queries, implement the most common queries — Select All, Insert, Delete and Select by ID. Replace everything inside the PeopleDao file with following:
package com.raywenderlich.android.imet.data.db
import android.arch.persistence.room.Dao
import android.arch.persistence.room.Insert
import android.arch.persistence.room.OnConflictStrategy
import android.arch.persistence.room.Query
import com.raywenderlich.android.imet.data.model.People
@Dao
interface PeopleDao {
// 1: Select All
@Query("SELECT * FROM People ORDER BY id DESC")
fun getAll(): List<People>
// 2: Insert
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(people: People)
// 3: Delete
@Query("DELETE FROM People")
fun deleteAll()
// 4: Select by id
@Query("SELECT * FROM People WHERE id = :id")
fun find(id: Int): People
}
That’s pretty straight forward! Similar to the @Entity
annotation, here, you use @Dao
on top of the interface to declare it as a DAO for your Room database.
Querying is fairly simple in Room. Reviewing the methods in PeopleDao
one by one:
-
getAll() returns a list of People entities. The
@Query
annotation on top performs a selection on your database and returns allPeople
as a list. In this query,SELECT * FROM People
, actually does the job andORDER BY id DESC
prepares the list with a descending order of people’sid
. -
insert(people: People) inserts new People entities in your database. While using the
@Insert
annotation is enough to perform the insertion for you, you can additionally addonConflict = OnConflictStrategy.REPLACE
for cases wherein your new People entity has the sameid
of an existing one in your database. In that case, it’ll replace (or update) the existing entity. - deleteAll() does exactly as its name implies — you perform a DELETE operation on the People entity in your database (remember, an Entity is like a Table in Room).
-
find(id: Int) is to find a People entity with specific
id
. It executes a SELECT query with a condition where the People‘sid
is matched to the suppliedid
parameter in this function.