forked from wbinarytree/android-architecture-components
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Sample showcasing migrations in Room
- Loading branch information
1 parent
9ba0514
commit 841c8b8
Showing
69 changed files
with
3,843 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
*.iml | ||
.gradle | ||
/local.properties | ||
/.idea/workspace.xml | ||
/.idea/libraries | ||
.DS_Store | ||
/build | ||
/captures | ||
.externalNativeBuild |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# Room Migration Sample | ||
|
||
This is an API sample to showcase how to deal with database migrations using Room. From [docs](https://developer.android.com/topic/libraries/architecture/room.html#db-migration): | ||
|
||
> As you add and change features in your app, you need to modify your entity classes to reflect these changes. When a user updates to the latest version of your app, you don't want them to lose all of their existing data, especially if you can't recover the data from a remote server. | ||
Room allows you to write [Migration](https://developer.android.com/reference/android/arch/persistence/room/migration/Migration.html) classes to preserve user data in this manner. Each [Migration](https://developer.android.com/reference/android/arch/persistence/room/migration/Migration.html) class specifies a startVersion and endVersion. At runtime, Room runs each [Migration](https://developer.android.com/reference/android/arch/persistence/room/migration/Migration.html) class's [migrate()](https://developer.android.com/reference/android/arch/persistence/room/migration/Migration.html#migrate(android.arch.persistence.db.SupportSQLiteDatabase) method, using the correct order to migrate the database to a later version. | ||
|
||
# Functionality | ||
The sample app shows an editable user name, stored in the database. | ||
|
||
# Implementation | ||
|
||
The UI layer uses the Model-View-Presenter design pattern and works with a `UserRepository` class. The `UserRepository` has a reference to the local repository to get and save the data. It ensures that all of these operations are done off the UI thread. The UI layer classes are common for all flavors. | ||
|
||
# Usage | ||
To showcase different implementations of the data layer product, flavors are used: | ||
|
||
* `sqlite` - Uses SQLiteOpenHelper and traditional SQLite interfaces. Database version is 1 | ||
* `room` - Replaces implementation with Room and provides migrations. Database version is 2. | ||
* `room` - Adds a new column to the table and provides migration Database version is 3. | ||
* `room` - Changes the type of the table's primary key from `int` to `String` and priovides migration. Database version is 4. | ||
|
||
# Building | ||
|
||
Use the Build Variants window in Android Studio to choose which version of the app you want to install, or alternatively choose one of the following tasks from the command line: | ||
|
||
``` | ||
$ ./gradlew installSqliteDebug | ||
$ ./gradlew installRoomDebug | ||
$ ./gradlew installRoom2Debug | ||
$ ./gradlew installRoom3Debug | ||
``` | ||
|
||
# Testing | ||
|
||
The project uses both instrumentation tests that run on the device and local unit tests that run on your computer. | ||
|
||
## Device Tests | ||
|
||
### Database Tests | ||
|
||
For the `sqlite` flavor the project is using the application database to test the functionality of `LocalUserDataSource` class. | ||
An in-memory database is used for `room` flavors `UserDao` and `LocalUserDataSource` tests, but still they are run on the device. | ||
An on-device database is used for the migration tests in all `room` flavors. | ||
|
||
## Local Unit Tests | ||
|
||
### Presenter Tests | ||
|
||
The `UserPresenter` is tested using local unit tests with mocked Repository implementation. | ||
|
||
### Repository Tests | ||
|
||
The `UserRepository` is tested using local unit tests with mocked `UserDataSource` and instant execution. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
/* | ||
* Copyright (C) 2017 The Android Open Source Project | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
apply plugin: 'com.android.application' | ||
|
||
android { | ||
compileSdkVersion rootProject.ext.compileSdkVersion | ||
buildToolsVersion rootProject.ext.buildToolsVersion | ||
|
||
defaultConfig { | ||
applicationId "com.example.android.persistence.migration" | ||
minSdkVersion rootProject.ext.minSdkVersion | ||
targetSdkVersion rootProject.ext.targetSdkVersion | ||
versionCode 1 | ||
versionName "1.0" | ||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" | ||
|
||
// used by Room, to test migrations | ||
javaCompileOptions { | ||
annotationProcessorOptions { | ||
arguments = ["room.schemaLocation": "$projectDir/schemas".toString()] | ||
} | ||
} | ||
} | ||
|
||
// used by Room, to test migrations | ||
sourceSets { | ||
androidTest.assets.srcDirs += files("$projectDir/schemas".toString()) | ||
|
||
// used by the room flavors to avoid duplication | ||
room.java.srcDirs += "src/room_common/java" | ||
room2.java.srcDirs += "src/room_common/java" | ||
room3.java.srcDirs += "src/room_common/java" | ||
|
||
androidTest.java.srcDirs += "src/androidTestRoom_Common/java" | ||
} | ||
|
||
buildTypes { | ||
release { | ||
minifyEnabled false | ||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' | ||
} | ||
} | ||
|
||
flavorDimensions "db" | ||
|
||
productFlavors { | ||
sqlite { | ||
// Uses SQLiteOpenHelper and traditional SQLite interfaces. Database version 1 | ||
dimension "db" | ||
} | ||
room { | ||
// Replaces implementation with Room and provides migrations to database version 2 | ||
dimension "db" | ||
} | ||
room2 { | ||
// Updates the DB to a new schema, database version 3 | ||
dimension "db" | ||
} | ||
room3 { | ||
// Updates the DB to a new schema, database version 4. | ||
// Provides migration paths to go from version 2 to 3, version 3 to 4 and version 2 to 4 | ||
dimension "db" | ||
} | ||
} | ||
|
||
// Remove mockRelease as it's not needed. | ||
android.variantFilter { variant -> | ||
if (variant.buildType.name.equals('release') | ||
&& variant.getFlavors().get(0).name.equals('mock')) { | ||
variant.setIgnore(true); | ||
} | ||
} | ||
|
||
} | ||
|
||
dependencies { | ||
//Support libraries | ||
implementation "com.android.support:appcompat-v7:$rootProject.supportLibraryVersion" | ||
implementation "com.android.support:support-v4:$rootProject.supportLibraryVersion" | ||
implementation "com.android.support:design:$rootProject.supportLibraryVersion" | ||
implementation "android.arch.persistence.room:runtime:$rootProject.roomVersion" | ||
annotationProcessor "android.arch.persistence.room:compiler:$rootProject.roomVersion" | ||
|
||
// Dependencies for local unit tests | ||
testImplementation "junit:junit:$rootProject.ext.junitVersion" | ||
testImplementation "org.mockito:mockito-all:$rootProject.ext.mockitoVersion" | ||
testImplementation "org.hamcrest:hamcrest-all:$rootProject.ext.hamcrestVersion" | ||
|
||
// Android Testing Support Library's runner and rules | ||
androidTestImplementation "com.android.support.test:runner:$rootProject.ext.runnerVersion" | ||
androidTestImplementation "com.android.support.test:rules:$rootProject.ext.runnerVersion" | ||
androidTestImplementation "android.arch.persistence.room:testing:$rootProject.roomVersion" | ||
|
||
// Dependencies for Android unit tests | ||
androidTestImplementation "junit:junit:$rootProject.ext.junitVersion" | ||
androidTestImplementation "org.mockito:mockito-core:$rootProject.ext.mockitoVersion" | ||
androidTestImplementation 'com.google.dexmaker:dexmaker:1.2' | ||
androidTestImplementation 'com.google.dexmaker:dexmaker-mockito:1.2' | ||
|
||
// Espresso UI Testing | ||
androidTestImplementation "com.android.support.test.espresso:espresso-core:$rootProject.espressoVersion" | ||
androidTestImplementation "com.android.support.test.espresso:espresso-contrib:$rootProject.espressoVersion" | ||
androidTestImplementation "com.android.support.test.espresso:espresso-intents:$rootProject.espressoVersion" | ||
|
||
// Resolve conflicts between main and test APK: | ||
androidTestImplementation "com.android.support:support-annotations:$rootProject.supportLibraryVersion" | ||
androidTestImplementation "com.android.support:support-v4:$rootProject.supportLibraryVersion" | ||
androidTestImplementation "com.android.support:appcompat-v7:$rootProject.supportLibraryVersion" | ||
androidTestImplementation "com.android.support:design:$rootProject.supportLibraryVersion" | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Add project specific ProGuard rules here. | ||
# By default, the flags in this file are appended to flags specified | ||
# in /Users/florinam/Library/Android/sdk/tools/proguard/proguard-android.txt | ||
# You can edit the include path and order by changing the proguardFiles | ||
# directive in build.gradle. | ||
# | ||
# For more details, see | ||
# http://developer.android.com/guide/developing/tools/proguard.html | ||
|
||
# Add any project specific keep options here: | ||
|
||
# If your project uses WebView with JS, uncomment the following | ||
# and specify the fully qualified class name to the JavaScript interface | ||
# class: | ||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview { | ||
# public *; | ||
#} | ||
|
||
# Uncomment this to preserve the line number information for | ||
# debugging stack traces. | ||
#-keepattributes SourceFile,LineNumberTable | ||
|
||
# If you keep the line number information, uncomment this to | ||
# hide the original source file name. | ||
#-renamesourcefileattribute SourceFile |
37 changes: 37 additions & 0 deletions
37
...rationsSample/app/schemas/com.example.android.persistence.migrations.UsersDatabase/2.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
{ | ||
"formatVersion": 1, | ||
"database": { | ||
"version": 2, | ||
"identityHash": "a146667337bb1ac18bbca63bc5d59421", | ||
"entities": [ | ||
{ | ||
"tableName": "users", | ||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userid` INTEGER, `username` TEXT, PRIMARY KEY(`userid`))", | ||
"fields": [ | ||
{ | ||
"fieldPath": "mId", | ||
"columnName": "userid", | ||
"affinity": "INTEGER" | ||
}, | ||
{ | ||
"fieldPath": "mUserName", | ||
"columnName": "username", | ||
"affinity": "TEXT" | ||
} | ||
], | ||
"primaryKey": { | ||
"columnNames": [ | ||
"userid" | ||
], | ||
"autoGenerate": false | ||
}, | ||
"indices": [], | ||
"foreignKeys": [] | ||
} | ||
], | ||
"setupQueries": [ | ||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", | ||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"a146667337bb1ac18bbca63bc5d59421\")" | ||
] | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
...rationsSample/app/schemas/com.example.android.persistence.migrations.UsersDatabase/3.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
{ | ||
"formatVersion": 1, | ||
"database": { | ||
"version": 3, | ||
"identityHash": "9ce74730f03594d59d1780980ad39b73", | ||
"entities": [ | ||
{ | ||
"tableName": "users", | ||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userid` INTEGER, `username` TEXT, `last_update` INTEGER, PRIMARY KEY(`userid`))", | ||
"fields": [ | ||
{ | ||
"fieldPath": "mId", | ||
"columnName": "userid", | ||
"affinity": "INTEGER" | ||
}, | ||
{ | ||
"fieldPath": "mUserName", | ||
"columnName": "username", | ||
"affinity": "TEXT" | ||
}, | ||
{ | ||
"fieldPath": "mDate", | ||
"columnName": "last_update", | ||
"affinity": "INTEGER" | ||
} | ||
], | ||
"primaryKey": { | ||
"columnNames": [ | ||
"userid" | ||
], | ||
"autoGenerate": false | ||
}, | ||
"indices": [], | ||
"foreignKeys": [] | ||
} | ||
], | ||
"setupQueries": [ | ||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", | ||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"9ce74730f03594d59d1780980ad39b73\")" | ||
] | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
...rationsSample/app/schemas/com.example.android.persistence.migrations.UsersDatabase/4.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
{ | ||
"formatVersion": 1, | ||
"database": { | ||
"version": 4, | ||
"identityHash": "12ffd58553365c5cebce6e857e5041eb", | ||
"entities": [ | ||
{ | ||
"tableName": "users", | ||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userid` TEXT, `username` TEXT, `last_update` INTEGER, PRIMARY KEY(`userid`))", | ||
"fields": [ | ||
{ | ||
"fieldPath": "mId", | ||
"columnName": "userid", | ||
"affinity": "TEXT" | ||
}, | ||
{ | ||
"fieldPath": "mUserName", | ||
"columnName": "username", | ||
"affinity": "TEXT" | ||
}, | ||
{ | ||
"fieldPath": "mDate", | ||
"columnName": "last_update", | ||
"affinity": "INTEGER" | ||
} | ||
], | ||
"primaryKey": { | ||
"columnNames": [ | ||
"userid" | ||
], | ||
"autoGenerate": false | ||
}, | ||
"indices": [], | ||
"foreignKeys": [] | ||
} | ||
], | ||
"setupQueries": [ | ||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", | ||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"12ffd58553365c5cebce6e857e5041eb\")" | ||
] | ||
} | ||
} |
Oops, something went wrong.