My data class to be used as an Entity
is as follows:
@Entity(tableName = "weather_response")
data class CurrentWeatherResponse(
@PrimaryKey(autoGenerate = false) var id_count: Int = 0,
@Embedded(prefix = "coord_") val coord: Coord,
@Embedded(prefix = "details_") @TypeConverters(value = [(DetailTypeConverters::class)]) @SerializedName("weather") val details: List<Details>,
val base: String,
@Embedded(prefix = "main_") val main: Main,
val visibility: Int,
@Embedded(prefix = "wind_") val wind: Wind,
val dt: Long,
@Embedded(prefix = "sys_") val sys: Sys,
val timezone: Int,
val name: String,
val cod: Int
)
My details object is a List of a custom class called Details
- which contains:
@Entity(tableName = "details")
data class Details(
val id: Int,
val main: String,
val description: String,
val icon: String
) {
@PrimaryKey(autoGenerate = false) var id_count = 0
}
This list will only have one item inside it. As mentioned in the data class above, I also have specified a TypeConverter class for that particular field in the entity. Its definition is below:
class DetailTypeConverters: Serializable {
companion object {
val gson = Gson()
@TypeConverter fun detailsToString(details: List<Details>): String {
return gson.toJson(details)
}
@TypeConverter fun stringtoDetails(value: String): List<Details> {
val type = object : TypeToken<List<Details>>() {}.type
return gson.fromJson(value, type)
}
}
}
Just to complete my question, here's my RoomDatabase
implementation as well:
@Database(
entities = [CurrentWeatherResponse::class,Coord::class,Main::class,Sys::class,Wind::class,Details::class],
version = 1
)
@TypeConverters(DetailTypeConverters::class)
abstract class ForecastDatabase: RoomDatabase() {
abstract fun currentWeatherDao(): CurrentWeatherDao
companion object {
@Volatile private var instance: ForecastDatabase? = null
private var LOCK = Any()
operator fun invoke(context: Context) = instance ?: synchronized(LOCK) {
instance ?: buildDatabase(context).also { instance = it }
}
private fun buildDatabase(context: Context) =
Room.databaseBuilder(context.applicationContext, ForecastDatabase::class.java, "forecast.db")
.build()
}
}
Going with this approach, I get the below error while building the app:
C:\Users\Spark\SimpleWeather\app\build\tmp\kapt3\stubs\debug\com\a5corp\weather\data\network\response\current\CurrentWeatherResponse.java:14: error: Cannot figure out how to save this field into database. You can consider adding a type converter for it.
private final com.a5corp.weather.data.network.response.current.Detail details = null;
Even I suspected something wrong because my IDE isn't showing the functions inside the DetailTypeConverters
to be used anywhere at all. Like this:
I know a lot of people have also posted solutions for similar kinds of problems in the past on StackOverflow. I did try a lot of them and tried to adapt to what I wanted. The solutions I tried out are:
- Using another class
- From a Medium post
- Adding @Embedded to the entity field
- Another TypeConverter, but adapted to Kotlin
Each one of them had the same problem - the same error message as posted above was being thrown while building the app. Also in each solution's custom TypeConverter that I had written, the two methods inside would always show the not being used highlighting in my Android Studio.
I'm also considering a move to Realm (if that can make things easier), but I would really like to explore all opportunities to make this work.