在kotlin成为android的第一种语言后,我全身心地投入到它中。随着这些天的一点进展,我一直在将我现有的知识迁移到kotlin中。最近,我正在学习如何在一个虚拟项目中使用GSON、改装和kotlin。
这里CurrentWeather
是在视图中显示数据的模型
data class CurrentWeather(
val latitude: Double,
val longitude: Double,
val placeName: String,
val temperature: Float,
val maxTemperature: Float,
val minTemperature: Float,
val windSpeed: Float,
val windDirection: Float,
val weatherType: String,
val weatherDescription: String,
val icon: String,
val timestamp: Instant)
类Current
负责将JSON解析为POJO类,就像我过去所做的那样,但现在使用kotlin 看起来有点不同
data class Current(@SerializedName("coord") val location: Location,
@SerializedName("weather") val weather: List<Weather>,
@SerializedName("main") val temperatureAndPressure: TemperatureAndPressure,
@SerializedName("wind") val wind: Wind,
@SerializedName("dt") val timeStamp: Long,
@SerializedName("name") val placeName: String) {
val time: Instant by fastLazy { Instant.ofEpochSecond(timeStamp) }
val currentWeather = CurrentWeather(location.latitude,
location.longitude,
placeName,
temperatureAndPressure.temperature,
temperatureAndPressure.maxTemperature,
temperatureAndPressure.minTemperature,
wind.windSpeed ?: 0f,
wind.windAngle ?: 0f,
weather[0].main,
weather[0].description,
weather[0].icon,
time)
}
即使我从改造中得到了成功的响应(我已经检查了成员变量;例如位置:位置,天气:列表,温度和压力:温度和压力等。然而,我收到了这个错误。
2018-11-12 21:04:07.455 9948-9948/bus.green.fivedayweather E/AndroidRuntime:致命异常:main流程:bus.green.fivedayweather,PID:9948java.lang.IollegalArgumentException:指定为非null的参数为null:方法kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull,参数p1在bus.green.feedayweather.ui.CurrentWeatherFragment$retrieveForecast$1.ioke(未知来源:6(在bus.green.feedayweather.ui.CurrentWeatherFragment$retrieveForecast$1.ioke(CurrentWeatherFragment.kt:20(在bus.green.feedayweather.net上。OpenWeatherMapProvider$ReformationCallbackWrapper.onResponse(OpenWeatherMapProvider.kt:62(
我在解析时做错了什么吗?
这是您的问题Parameter specified as non-null is null
。所有的数据类都是用non-null parameter constructor
声明的。然而,在解析JSON过程中,有一个null参数-->导致崩溃。为了解决这个问题,您应该声明构造函数参数为null,如下所示:
data class Current(@SerializedName("coord") val location: Location?,
@SerializedName("weather") val weather: List<Weather>?,
@SerializedName("main") val temperatureAndPressure: TemperatureAndPressure?,
@SerializedName("wind") val wind: Wind?,
@SerializedName("dt") val timeStamp: Long?,
@SerializedName("name") val placeName: String?) {
// your CurrentWeather class should be the same.
// Of course, if you are sure with non-null parameters, you should make them non-null.
我相信,如果按照上面的解决方案,使变量的类型可以为null,并不能解决您的问题。在您的案例中,问题在于Gson本身的JSON解析。首先,Gson没有对Kotlin数据类的原生支持。我建议你通读这篇文章GSON+KOTLIN。这篇文章的简短摘要是
- 当我们考虑到开发人员在使用不可为null的类型时对null安全性的假设时,这一点尤其糟糕。它将在运行时导致NullPointerException,IDE没有提示可能的可为null性。在解析时,我们甚至不会得到异常,因为Gson使用了不安全的反射,而Java并没有不可为null的类型的概念
- 处理这一问题的一种方法是让步,让一切都可以为空,就像@Kingfisher Phuoc提出的答案一样。不幸的是,这不仅仅是让代码运行。原因是您的成员变量
val currentWeather
是数据类的实例,而使用reflect的Gson无法从取消序列化的JSON中实例化它,因此即使您正确解析了data class Current
的成员变量,它也将为null
我的建议是切换到Moshi,它内置了对Kotlin的支持。相反,如果你是Gson的超级粉丝,你需要在默认值和使变量为null类型的帮助下遵循这个解决方法。为此,我们基本上将构造函数参数设置为私有支持属性。然后,我们为每个具有真实名称的支持字段提供一个只读属性,并使用自定义get((=与Elvis运算符组合来定义我们的默认值或行为,从而产生不可为null的返回值。
data class Current(@SerializedName("coord") val _location: Location?,
@SerializedName("weather") val _weather: List<Weather>?,
@SerializedName("main") val _temperatureAndPressure: TemperatureAndPressure?,
@SerializedName("wind") val _wind: Wind?,
@SerializedName("dt") val _timeStamp: Long?, = 0.0
@SerializedName("name") val _placeName: String? = "") {
val location
get() = _location ?: throw IllegalArgumentException("Location is required")
val weather
get() = _weather ?: throw IllegalArgumentException("Title is required")
val wind
get() = _wind ?: throw IllegalArgumentException("Title is required")
val temperatureAndPressure
get() = _temperatureAndPressure ?: throw IllegalArgumentException("Title is required")
......and so on
val time: Instant by fastLazy { Instant.ofEpochSecond(timeStamp) }
val currentWeather = CurrentWeather(location.latitude,
location.longitude,
placeName,
temperatureAndPressure.temperature,
temperatureAndPressure.maxTemperature,
temperatureAndPressure.minTemperature,
wind.windSpeed ?: 0f,
wind.windAngle ?: 0f,
weather[0].main,
weather[0].description,
weather[0].icon,
time)
}
在我看来,在科特林统治世界的这些日子里,Gson没能跟上步伐。如果你只是为了学习而做这个项目,你绝对应该使用Moshi它有KotlinJsonAdapterFactory
,它开箱即用地支持JSON