Custom Type
Persist non-primitive types in Room using TypeConverters or Embedded types.
Type Converter
Type converters are pairs of functions, annotated with @TypeConverter, that translate a single database column type to a Kotlin property type and back.
Typical uses:
- Map an
Instantto aLongfor a SQLiteintegercolumn. - Map a
Locationto aStringfor a SQLitetextcolumn. - Map a collection of
Stringto a singleString(e.g., CSV) for atextcolumn.
Setting Up a Type Converter
- Create any Kotlin class to hold converter functions.
- For each type pair, create two functions: A→B and B→A. If input is
null, returnnull. Ensure the round-trip preserves values. - Annotate both functions with
@TypeConverter. - Bring them into scope with
@TypeConverterson one of:
| @TypeConverters on… | Applies to… |
|---|---|
| RoomDatabase | everything in the database |
| Entity class | all properties in that entity |
| Entity property | that property only |
| DAO class | all DAO functions |
| DAO function | that function (all params) |
| DAO function parameter | that single parameter |
Example: an entity using converters for Instant, Location, and Set<String>:
@Entity(tableName = "record")
@TypeConverters(InstantTypeConverter::class, LocationTypeConverter::class, SetTypeConverter::class)
data class Record(
@PrimaryKey(autoGenerate = true)
val id: Long = 0,
val instant: Instant = Clock.System.now(),
val location: Location,
val tags: Set<String> = setOf()
) {
@Dao
interface SQL {
@Query("select * from record")
suspend fun select(): List<Record>
@Insert
suspend fun insert(entity: Record)
}
}
data class Location(val latitude: Double, val longitude: Double) {
constructor(location: Location) : this(location.latitude, location.longitude)
}InstantTypeConverter
SQLite does not have a native date/time type. The recommended approach is to store timestamps as the number of milliseconds since the Unix epoch (January 1, 1970, 00:00:00 UTC).
Instant has a toEpochMilliseconds() function that returns this value.
class InstantTypeConverter {
@TypeConverter
fun instantToLong(timestamp: Instant?) = timestamp?.toEpochMilliseconds()
@TypeConverter
fun longToInstant(timestamp: Long?) =
timestamp?.let { Instant.fromEpochMilliseconds(it) }
}With @TypeConverters(InstantTypeConverter::class) in scope, Room will persist Instant as a SQLite integer.
LocationTypeConverter
Persist a Location (latitude/longitude) as a single String in a text column (e.g., “latitude;longitude”):
A Location object contains a latitude, longitude, and perhaps other values (e.g., altitude). If we only care about the latitude and longitude, we could save those in the database in a single text column, so long as we can determine a good format to use for that string. One possibility is to have the two values separated by a semicolon.
The LocationTypeConverter class has a pair of functions designed to convert between a Location and a String:
class LocationTypeConverter {
@TypeConverter
fun locationToString(location: Location?) =
location?.let { "${it.latitude};${it.longitude}" }
@TypeConverter
fun stringToLocation(location: String?) = location?.let {
val pieces = location.split(';')
if (pieces.size == 2) {
try {
Location(pieces[0].toDouble(), pieces[1].toDouble())
} catch (e: Exception) {
null
}
} else {
null
}
}
}Estàs llegint una vista prèvia.
Inicia sessió amb Google per llegir la pàgina completa.
Inicia sessió amb GoogleAmb qualsevol compte de Google. Només et demanarem que acceptis les condicions del servei.