This is the way we create a database using the Room library:
database = Room.databaseBuilder(
this,
WordInfoDatabase::class.java,
"word_db"
).addTypeConverter(Converters(GsonParser(Gson())))
.build()
We can specify there what custom converter we want to use by the method addTypeConverter(typeConverter: Any). The typeConverter class' methods can have any names varying from toJson or fromJson to just qwerty, they can also take different data types as the parameter and return different data types as the result, e.g.
@TypeConverter
fun instantToLong(timestamp: Instant?) = timestamp?.toEpochMilli()
@TypeConverter
fun longToInstant(timestamp: Long?) =
timestamp?.let { Instant.ofEpochMilli(it) }
or
@ProvidedTypeConverter
class Converters(
private val jsonParser: JsonParser
) {
@TypeConverter
fun fromMeaningsJson(json: String): List<Meaning> {
return jsonParser.fromJson<ArrayList<Meaning>>(
json,
object : TypeToken<ArrayList<Meaning>>(){}.type
) ?: emptyList()
}
@TypeConverter
fun toMeaningsJson(meanings: List<Meaning>): String {
return jsonParser.toJson(
meanings,
object : TypeToken<ArrayList<Meaning>>(){}.type
) ?: "[]"
}
}
So how does Room know how to use them properly?
When you compile the project the Room annotations result in underlying java code being generated according to the room-compiler annotation processor and it is through invocation of the generated code that the Type Converters are used.
Consider a simplified version of your code, with some assumed additional classes:-
First a Meaning class (that will be converted):-
And an associated pair of
TypeConverterfunctions (annotated accordingly) for the Meaning class in the Converters class:-An
@Entity, class for a table that has a Meaning within a column that will require type conversion:-An
@Daoannotated interface with 2 functions (Insert and Extract) that will require type conversion to take placeFinally an
@Databaseannotated abstract class that is@Entityannotated class@Daointerface (so they are included)@Databasewith the respective@Entity's and the respective@Dao`s) that drives the generation of the generated java.:-
When the above is compiled then (via the Android View):-
So as can be seen there are two relevant java classes. One for the
@Daoannotated interface (more if more@Daoannotated interfaces) with the same name but suffixed with _Impl. The other likewise for the@Databaseannotated class (more if more@Databaseannotated classes), again suffixed with _Impl.It is from the the AllDAO_Impl class where you can see how the TypeConverter functions are implemented/called:-