改造响应对象中的嵌入式房间实体字段未在运行时初始化

Embedded room entity field in retrofit response object not initialized at runtime

我有一个 CurrentWeatherResponse 对象,其中包含使用 Retrofit 从天气 API 恢复的 JSON 数据。这是 JSON 响应格式:

{
"latitude": 37.8267,
"longitude": -122.4233,
"timezone": "America/Los_Angeles",
"currently": {
  "time": 1587054875,
  "summary": "Mostly Cloudy",
  "icon": "partly-cloudy-day",
  "nearestStormDistance": 107,
  "nearestStormBearing": 119,
  "precipIntensity": 0,
  "precipProbability": 0,
  "temperature": 11.49,
  "apparentTemperature": 11.49,
  "dewPoint": 10.14,
  "humidity": 0.91,
  "pressure": 1012.9,
  "windSpeed": 2.73,
  "windGust": 3.84,
  "windBearing": 171,
  "cloudCover": 0.64,
  "uvIndex": 2,
  "visibility": 16.093,
  "ozone": 360.9
  },
"offset": -7
}

CurrentWeatherResponse 中,我分别有两个字段 currentWeatherEntry: CurrentWeatherEntryval location: WeatherLocation。这些字段中的每一个都是一个房间 @Entity class。现在我注意到,尽管 "currently" json 数据已成功传递到 CurrentWeatherEntry 字段,但 @Embedded 位置 WeatherLocation 字段从未初始化。当我 运行 应用程序或使用数据库检查器时,我可以看到 WeatherLocation 实体甚至没有初始化其 ID 字段。我在这里错过了什么?

当前天气响应class:

data class CurrentWeatherResponse(
    // Tells GSON that the "currently" field of the JSON returned by the
    // API should be tied with our CurrentWeatherEntry data class
    @SerializedName("currently")
    val currentWeatherEntry: CurrentWeatherEntry,
    @Embedded
    val location: WeatherLocation
) {
    init {
        location.setEpochTimeVal(currentWeatherEntry.time)
    }
}

CurrentWeatherEntry 实体:

const val CURRENT_WEATHER_ID = 0

@Entity(tableName = "current_weather")
data class CurrentWeatherEntry(
    val time: Long, // epoch timestamp
    val icon: String,
    val summary: String,
    val precipProbability: Double,
    val temperature: Double
) {
    @PrimaryKey(autoGenerate = false)
    var id:Int = CURRENT_WEATHER_ID
}

WeatherLocaiton 实体:

const val WEATHER_LOCATION_ID = 0

@Entity(tableName = "weather_location")
data class WeatherLocation(
    val latitude: Double,
    val longitude: Double,
    val timezone: String
) {
    @PrimaryKey(autoGenerate = false)
    var id:Int = WEATHER_LOCATION_ID

    private var epochTimeVal:Long = 0

    val zonedDateTime:ZonedDateTime
        get() {
            val instant = Instant.ofEpochMilli(this.epochTimeVal)
            val zoneId = ZoneId.of(timezone)
            return ZonedDateTime.ofInstant(instant,zoneId)
        }

    fun setEpochTimeVal(time:Long) {
        this.epochTimeVal = time}
    fun getEpochTimeVal() : Long = epochTimeVal
}

如果我正确理解了你的问题,我不得不说 @Embedded 注释是 Room 的注释,而不是 Gson 的注释。因此,通过 Retrofit 将您的响应转换为 Kotlin 数据对象不会发挥作用。

@Embedded 注释仅对 Room Dao 可见 class 以将关系数据库转换为您方便的对象模型。

因此您需要为 Gson 编写自己的 TypeConvertor

如@MahdiRajabi 所述,@Embedded 注释由 Room 使用,而不是 Gson。这意味着从 JSON 响应返回到 CurrentWeatherResponse class 的 latitudelongitudetimezone 字段被简单地忽略并且location:WeatherLocation 字段被简单分配 null。我通过在 CurrentWeatherResponse 中显式定义 latitudelongitudetimezone 字段然后在 [=23= 时返回 WeatherLocation 的实例来解决我的问题] 字段使用 getter 访问。现在一切正常!

data class CurrentWeatherResponse(
    // Tells GSON that the "currently" field of the JSON returned by the
    // API should be tied with our CurrentWeatherEntry data class
    @SerializedName("currently")
    val currentWeatherEntry: CurrentWeatherEntry,
    val latitude:Double,
    val longitude:Double,
    val timezone:String
) {
    val location:WeatherLocation
        get() = WeatherLocation(latitude,longitude,timezone,currentWeatherEntry.time)
}