Step #5: Creating a Transmogrifier

If you try building the project — for example, Build > “Make module ‘app’” from the Android Studio main menu — you will get build errors, such as:

error: Cannot figure out how to save this field into database. You can consider adding a type converter for it. private final java.time.Instant createdOn = null;

The problem is that Room does not know what to do with an Instant object. SQLite does not have a native date/time column type, and Room cannot convert arbitrary objects into arbitrary SQLite column types. Instead, Room’s annotation processor detects the issue and fails the build.

To fix this, we need to teach Room how to convert Instant objects to and from some standard SQLite column type. And for that… we could really use another Kotlin class. Fortunately, you can never have too many Kotlin classes!

(NARRATOR: you definitely can have too many Kotlin classes, but one more will not hurt)

Right-click over the com.commonsware.todo.repo package in the java/ directory and choose “New” > “Kotlin File/Class” from the context menu. For the name, fill in TypeTransmogrifier. But, this time, choose “Object” for the kind. Press Enter or Return to create the class, giving you:

package com.commonsware.todo.repo

object TypeTransmogrifier {
}

A transmogrifier is a ~30-year-old piece of advanced technology that can convert one thing into another. Here, we are creating a type transmogrifier: a set of functions that turn one type into another.

To that end, replace the stub generated class with this:

package com.commonsware.todo.repo

import androidx.room.TypeConverter
import java.time.Instant

object TypeTransmogrifier {
  @TypeConverter
  fun fromInstant(date: Instant?): Long? = date?.toEpochMilli()

  @TypeConverter
  fun toInstant(millisSinceEpoch: Long?): Instant? = millisSinceEpoch?.let {
    Instant.ofEpochMilli(it)
  }
}

The @TypeConverter annotations tell Room that this is a function that can convert one type into another. Here, we convert Instant objects into Long objects, using the time-since-the-Unix-epoch methods on Instant.

Then, add this annotation to the ToDoDatabase class declaration, under the existing @Database annotation:

@TypeConverters(TypeTransmogrifier::class) 

This tells Room that for any entities used by this ToDoDatabase, if you need to convert a type, try looking for @TypeConverter methods on TypeTransmogrifier.

Now, if you choose Build > “Make module ‘app’” from the Android Studio main menu, the app should build successfully.


Prev Table of Contents Next

This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.