Adding a Suspect to the Model Layer

Next, open Crime.kt and give Crime a property that will hold the name of a suspect.

Listing 15.3  Adding a suspect property (Crime.kt)

@Entity
data class Crime(@PrimaryKey val id: UUID = UUID.randomUUID(),
                 var title: String = "",
                 var date: Date = Date(),
                 var isSolved: Boolean = false,
                 var suspect: String = "")

Now you need to add an additional property to your crime database. This requires incrementing the version of your CrimeDatabase class, as well as telling Room how to migrate your database between the versions.

To tell Room how to change your database from one version to another, you provide a Migration. Open CrimeDatabase.kt, add a migration, and increment the version.

Listing 15.4  Adding database migration (database/CrimeDatabase.kt)

@Database(entities = [ Crime::class ], version=1 version=2)
@TypeConverters(CrimeTypeConverters::class)
abstract class CrimeDatabase : RoomDatabase() {

    abstract fun crimeDao(): CrimeDao
}

val migration_1_2 = object : Migration(1, 2) {
    override fun migrate(database: SupportSQLiteDatabase) {
        database.execSQL(
            "ALTER TABLE Crime ADD COLUMN suspect TEXT NOT NULL DEFAULT ''"
        )
    }
}

Since your initial database version is set to 1, you bump it up to 2. You then create a Migration object that contains instructions for updating your database.

The Migration class constructor takes in two parameters. The first is the database version you are migrating from, and the second is the version you are migrating to. In this case, you provide the version numbers 1 and 2.

The only function you need to implement in your Migration object is migrate(SupportSQLiteDatabase). You use the database parameter to execute any SQL commands necessary to upgrade your tables. (Room uses SQLite under the hood, as you read in Chapter 11.) The ALTER TABLE command you wrote adds the new suspect column to the crime table.

After you create your Migration, you need to provide it to your database when it is created. Open CrimeRepository.kt and provide the migration to Room when creating your CrimeDatabase instance.

Listing 15.5  Providing migration to Room (CrimeRepository.kt)

class CrimeRepository private constructor(context: Context) {

    private val database : CrimeDatabase = Room.databaseBuilder(
        context.applicationContext,
        CrimeDatabase::class.java,
        DATABASE_NAME
    ).build()
    ).addMigrations(migration_1_2)
        .build()
    private val crimeDao = database.crimeDao()
    ...
}

To set up the migration, you call addMigrations(…) before calling the build() function. addMigrations() takes in a variable number of Migration objects, so you can pass all of your migrations in when you declare them.

When your app launches and Room builds the database, it will first check the version of the existing database on the device. If this version does not match the one you define in the @Database annotation, Room will search for the appropriate migrations to update the database to the latest version.

It is important to provide migrations for converting your database. If you do not provide migrations, Room will delete the old version of the database and re-create a new version. This means that all the data will be lost, leading to very unhappy users.

Once your migration is in place, run CriminalIntent to make sure everything builds correctly. The app behavior should be the same as before you applied the migration, and you should see the crime you added in Chapter 14. You will make use of the newly added column shortly.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.115.195