Android	Jetpack		
Room	Persistence	Library
Huỳnh	Quang	Thảo	
Trusting	Social	
Google	Developer	Expert	on	Android
When	start	new	android	app	…
- Database:	
- Native	SQLite	
- ORM	wrapper	on	SQLite:	DBFlow	
- Different	database	engines:	Realm.
When	start	new	android	app	…
- 	Running	a	jobs:	
- AlarmManager	+	Broadcast	Receiver	
- Firebase	JobDispatcher	
- JobScheduler	
- GCMNetworkManager	
-
When	start	new	android	app	…
- Control	data	Slow	and	update	latest	data	on	UI.
When	start	new	android	app	…
- Control	data	Slow	and	update	latest	data	on	UI.	
- Loading	data:	
- Loading	data	from	network.	
- Loading	data	from	on-device	database.	
- Loading	data	from	multiple	sources.
Android	Architecture	Components
ViewModel
Live	Data
World	before	Room
-SQL	boiler	code	
-Migration	
-Testing
Solutions
GreenDAO
Realm
DBFlow
Why	Room
-provides	an	abstraction	layer	over	SQLite.
Why	Room
-provides	an	abstraction	layer	over	SQLite.	
-Provide	compile-time	checking	for	SQL	Statement.
Why	Room
-provides	an	abstraction	layer	over	SQLite.	
-Provide	compile-time	checking	for	SQL	Statement.	
-Detect	query	database	on	main	thread.
Why	Room
-provides	an	abstraction	layer	over	SQLite.	
-Provide	compile-time	checking	for	SQL	Statement.	
-Detect	query	database	on	main	thread.	
-Easier	for	testing	and	migration.
Room	Components
Entity
public class Word {
private String mWord;
public Word(String word) {this.mWord = word;}
public String getWord(){return this.mWord;}
}
Entity
@Entity(tableName = "word_table")
public class Word {
@PrimaryKey
@NonNull
@ColumnInfo(name = "word")
private String mWord;
public Word(String word) {this.mWord = word;}
public String getWord(){return this.mWord;}
}
Entity
-Support	database	constraints.	(unique	key,	primary	keys	…)
Entity
-Support	database	constraints.	(unique	key,	primary	keys	…)	
-Support	deSine	relationship	between	model.
Entity
-Support	database	constraints.	(unique	key,	primary	keys	…)	
-Support	deSine	relationship	between	model.	
-Can	ignore	derived	Sields.
Entity
-Support	database	constraints.	(unique	key,	primary	keys	…)	
-Support	deSine	relationship	between	model.	
-Can	ignore	derived	Sields.	
-Support	database	views.
DAO
@Dao
public interface WordDao {
@Insert
void insert(Word word);
@Query("DELETE FROM word_table")
void deleteAll();
@Query("SELECT * from word_table ORDER BY word ASC")
LiveData<List<Word>> getAllWords();
}
DAO
-Use	annotation	for	simple	actions	such	as	insert/delete/update
@Dao
public interface WordDao {
@Insert
void insert(Word word);
}
DAO
-Write	custom	query.
@Dao
public interface WordDao {
@Query("DELETE FROM word_table")
void deleteAll();
@Query("SELECT * from word_table ORDER BY word ASC")
LiveData<List<Word>> getAllWords();
}
DAO
-Check	query	at	compile	time.
DAO
-Check	query	at	compile	time.
DAO
-Return	LiveData	data.
@Dao
public interface WordDao {
@Query("SELECT * from word_table ORDER BY word ASC")
LiveData<List<Word>> getAllWords();
}
Room	Database
-Abstraction	over	SQLiteHelper.
@Database(entities = {Word.class}, version = 1)
public abstract class WordRoomDatabase extends RoomDatabase {
public abstract WordDao wordDao();
private static volatile WordRoomDatabase INSTANCE;
static WordRoomDatabase getDatabase(final Context context) {
if (INSTANCE == null) {
synchronized (WordRoomDatabase.class) {
if (INSTANCE == null) {
// Create database here
INSTANCE =
Room.databaseBuilder(context.getApplicationContext(),
WordRoomDatabase.class, "word_database")
.addCallback(sRoomDatabaseCallback)
.build();
}
}
}
return INSTANCE;
}
}
Room	Database
Sample	application
Codelab:	
https://codelabs.developers.google.com/codelabs/android-room-with-a-view/#0	
Code	demo:	
https://github.com/googlecodelabs/android-room-with-a-view
WorkSlow
7	steps	to	to	Room
https://medium.com/androiddevelopers/7-steps-to-room-27a5fe5f99b2
Step	1:	Add	dependencies
dependencies {
// Room components
implementation "android.arch.persistence.room:runtime:$rootProject.roomVersion"
annotationProcessor "android.arch.persistence.room:compiler:$rootProject.roomVersion"
androidTestImplementation "android.arch.persistence.room:testing:$rootProject.roomVersion"
// Lifecycle components
implementation "android.arch.lifecycle:extensions:$rootProject.archLifecycleVersion"
annotationProcessor "android.arch.lifecycle:compiler:$rootProject.archLifecycleVersion"
}
build.gradle	(module	app)
Step	2:	Update	model	to	entity
@Entity(tableName = "word_table")
public class Word {
@PrimaryKey
@NonNull
@ColumnInfo(name = "word")
private String mWord;
public Word(String word) {this.mWord = word;}
public String getWord(){return this.mWord;}
}
Step	3:	Create	DAO
@Dao
public interface WordDao {
@Insert
void insert(Word word);
}
Step	3:	Create	DAO
@Dao
public interface WordDao {
@Insert
void insert(Word word);
@Query("DELETE FROM word_table")
void deleteAll();
@Query("SELECT * from word_table ORDER BY word ASC")
LiveData<List<Word>> getAllWords();
}
Step	4:	Create	Database
@Database(entities = {Word.class}, version = 1)
public abstract class WordRoomDatabase extends RoomDatabase {
}
Step	4:	Create	Database
@Database(entities = {Word.class}, version = 1)
public abstract class WordRoomDatabase extends RoomDatabase {
public abstract WordDao wordDao();
}
Step	4:	Create	Database
@Database(entities = {Word.class}, version = 1)
public abstract class WordRoomDatabase extends RoomDatabase {
public abstract WordDao wordDao();
private static volatile WordRoomDatabase INSTANCE;
static WordRoomDatabase getDatabase(final Context context) {
if (INSTANCE == null) {
synchronized (WordRoomDatabase.class) {
if (INSTANCE == null) {
// Create database here
INSTANCE =
Room.databaseBuilder(context.getApplicationContext(),
WordRoomDatabase.class, "word_database")
.addCallback(sRoomDatabaseCallback)
.build();
}
}
}
return INSTANCE;
}
}
Step	5:	Update	Repository
public class WordRepository {
private WordDao mWordDao;
private LiveData<List<Word>> mAllWords;
}
Step	5:	Update	Repository
public class WordRepository {
private WordDao mWordDao;
private LiveData<List<Word>> mAllWords;
public WordRepository(Application application) {
WordRoomDatabase db = WordRoomDatabase.getDatabase(application);
mWordDao = db.wordDao();
mAllWords = mWordDao.getAllWords();
}
public LiveData<List<Word>> getAllWords() {
return mAllWords;
}
public void insert(Word word) {
new insertAsyncTask(mWordDao).execute(word);
}
}
Step	6:	Testing	DAO
@RunWith(AndroidJUnit4.class)
public class WordDaoTest {
private WordDao mWordDao;
private WordRoomDatabase mDb;
@Before
public void createDb() {
Context context = InstrumentationRegistry.getTargetContext();
mDb = Room.inMemoryDatabaseBuilder(context, WordRoomDatabase.class)
// Allowing main thread queries, just for testing.
.allowMainThreadQueries()
.build();
mWordDao = mDb.wordDao();
}
@After
public void closeDb() {
mDb.close();
}
}
Step	6:	Testing	DAO
@RunWith(AndroidJUnit4.class)
public class WordDaoTest {
private WordDao mWordDao;
private WordRoomDatabase mDb;
@Before
public void createDb() {
Context context = InstrumentationRegistry.getTargetContext();
mDb = Room.inMemoryDatabaseBuilder(context, WordRoomDatabase.class)
// Allowing main thread queries, just for testing.
.allowMainThreadQueries()
.build();
mWordDao = mDb.wordDao();
}
@After
public void closeDb() {
mDb.close();
}
@Test
public void insertAndGetWord() throws Exception {
Word word = new Word("word");
mWordDao.insert(word);
List<Word> allWords = LiveDataTestUtil.getValue
(mWordDao.getAlphabetizedWords());
assertEquals(allWords.get(0).getWord(), word.getWord());
}
}
Step	7:	Clean	up
- Remove	unused	classes	replaced	by	Room.	(i.e:	any	class	extends	SQLiteHelper)	
- More	complex	project:	
- https://medium.com/androiddevelopers/incrementally-migrate-from-sqlite-to-room-66c2f655b377
Learning	References
Android	architecture	components	
-	https://developer.android.com/jetpack/docs/guide
Learning	References
Android	architecture	components	
-	https://developer.android.com/jetpack/docs/guide	
Android	LifeCycle	components	
- https://www.youtube.com/watch?v=5qlIPTDE274	
- https://developer.android.com/topic/libraries/architecture/lifecycle
Learning	References
Android	architecture	components	
-	https://developer.android.com/jetpack/docs/guide	
Android	LifeCycle	components	
- https://www.youtube.com/watch?v=5qlIPTDE274	
- https://developer.android.com/topic/libraries/architecture/lifecycle	
Android	LiveData	
-	https://www.youtube.com/watch?v=OMcDk2_4LSk	
-	https://developer.android.com/topic/libraries/architecture/livedata
Learning	References
Android	architecture	components	
-	https://developer.android.com/jetpack/docs/guide	
Android	LifeCycle	components	
- https://www.youtube.com/watch?v=5qlIPTDE274	
- https://developer.android.com/topic/libraries/architecture/lifecycle	
Android	LiveData	
-	https://www.youtube.com/watch?v=OMcDk2_4LSk	
-	https://developer.android.com/topic/libraries/architecture/livedata	
Room	Persistence	libraries	
-	https://developer.android.com/topic/libraries/architecture/room	
-	https://www.youtube.com/watch?v=SKWh4ckvFPM
Learning	References
Android	architecture	components	
-	https://developer.android.com/jetpack/docs/guide	
Android	LifeCycle	components	
- https://www.youtube.com/watch?v=5qlIPTDE274	
- https://developer.android.com/topic/libraries/architecture/lifecycle	
Android	LiveData	
-	https://www.youtube.com/watch?v=OMcDk2_4LSk	
-	https://developer.android.com/topic/libraries/architecture/livedata	
Room	Persistence	libraries	
-	https://developer.android.com/topic/libraries/architecture/room	
-	https://www.youtube.com/watch?v=SKWh4ckvFPM	
Paging	
-	https://developer.android.com/topic/libraries/architecture/paging/
Codelab
- https://codelabs.developers.google.com/codelabs/android-lifecycles/#1	
- https://codelabs.developers.google.com/codelabs/android-persistence/#0	
- https://codelabs.developers.google.com/codelabs/android-room-with-a-view/#0	
- https://codelabs.developers.google.com/codelabs/android-paging/#0
Q&A

Android Jetpack: Room persistence library