在 Retrofit 中——获取 NULL 作为响应,但结果列在日志中
In Retrofit- Getting NULL as Response but the results are listed in logs
我尝试使用 Retrofit 从响应中获取数据,但我得到的是 空值 。
如果我敬酒响应它总是空但响应显示在日志中但它不是
加载到 Recyclerview
请帮我完成这个面试任务
我的实际反应
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"title": "Stolen 2021 Specialized Sirrus 2.0 (03-14-2021)",
"description": "<img src='https://files.bikeindex.org/uploads/Pu/408280/large_IMG_5771.JPG'> <a target=\"_blank\" href=\"https://bikeindex.org/bikes/1018433\">View details</a>",
"occurred_at": "2021-03-14 22:31:13 -0500",
"marker-size": "small",
"marker-color": "#E74C3C",
"id": 136982
},
"geometry": {
"type": "Point",
"coordinates": [
-122.65,
45.51
]
}
}
ApiClient Class
object ApiClient {
var BASE_URL: String = "https://bikewise.org:443/api/v2/locations/"
val getClient: ApiInterfac
get() {
val gson = GsonBuilder().setLenient().create()
val interceptor = HttpLoggingInterceptor()
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY)
val client = OkHttpClient.Builder().addInterceptor(interceptor).build()
val retrofit = Retrofit.Builder().baseUrl(BASE_URL).client(client).addConverterFactory(GsonConverterFactory.create(gson)).build()
return retrofit.create(ApiInterfac::class.java)
}
}
ApiInterface class:
@GET("markers?proximity=45.521728%2C-122.67326&proximity_square=100")
fun getVideoList(): Call < DataVideos >
}
型号Class
data class DataVideos(
// @SerializedName("type")
var listme:List<Videos>,
@SerializedName("title")
var title:String,
@SerializedName("description")
var description: String)
下面是来自 var listme:List 的视频 Class
class Videos {
@SerializedName("title")
val title: String? = null
@SerializedName("description")
val description: String? = null
}
我的数据变得有趣
private fun getDat1a() {
Log.d(TAG, "GetDataFun")
val call: Call < DataVideos > = ApiClient .getClient.getVideoList()
call.enqueue(object: Callback < DataVideos > {
override fun onResponse(call: Call < DataVideos > ? , response : Response < DataVideos > ? ) {
if(response!!.isSuccessful){
Toast.makeText(activity?.applicationContext!!,"Data:"+response!!.body()!!.listme,Toast.LENGTH_LONG).show()
val rst=response!!.body()
progerssProgressDialog.dismiss()
dataList.addAll(listOf(rst!!))
recyclerView.adapter!!.notifyDataSetChanged()
}
}
override fun onFailure(call: Call < DataVideos> ? , t : Throwable ? ) {
progerssProgressDialog.dismiss()
Log.d(TAG, "Failes"+t)
}
})
}
I'm getting null in Toast as well in recyclerview but in logs i can find the data
我的日志可以显示输出
{"type":"FeatureCollection","features":[{"type":"Feature","properties":{"title":"Stolen 2021 Specialized Sirrus 2.0 (03-14-2021)","description":"\u003cimg src='https://files.bikeindex.org/uploads/Pu/408280/large_IMG_5771.JPG'\u003e \u003ca target=\"_blank\" href=\"https://bikeindex.org/bikes/1018433\"\u003eView details\u003c/a\u003e","occurred_at":"2021-03-14 22:31:13 -0500","marker-size":"small","marker-color":"#E74C3C","id":136982},"geometry":{"type":"Point","coordinates":[-122.65,45.51]}},{"type":"Feature","properties":{"title":"Stolen 2018 Surly Straggler (01-13-2021)","description":"\u003cimg src='https://files.bikeindex.org/uploads/Pu/144946/large_IMG_4383.jpg'\u003e Break in to my garage. \u003ca target=\"_blank\" href=\"https://bikeindex.org/bikes/516282\"\u003eView details\u003c/a\u003e","occurred_at":"2021-01-13 05:00:00 -0600","marker-size":"small","marker-color":"#EE8276","id":134325},"geometry":{"type":"Point","coordinates":[-122.69,45.59]}}]}
2021-03-18 09:26:45.027 7776-8035/com.lab.optisol I/okhttp.OkHttpClient: <-- END HTTP (51772-byte body)
将此模型用于响应
fun getVideoList(): Call<YourResponse>
data class YourResponse(
val type: String? = null,
val features: ArrayList<Features>? = null
)
data class Features(
val type: String? = null,
val properties: Properties? = null,
val geometry:Geometry?=null
)
class Properties(
@SerializedName("title")
@Expose
val title: String? = null,
@SerializedName("description")
@Expose
val description: String? = null,
@SerializedName("occurred_at")
@Expose
val occurred_at: String? = null,
@SerializedName("marker-size")
@Expose
val marker_size: String? = null,
@SerializedName("marker-color")
@Expose
val marker_color: String? = null,
@SerializedName("id")
@Expose
val id: Int? = null
)
data class Geometry(
val type:String?=null,
val coordinates:ArrayList<Double>?=null
)
您的 DataVideo
class 不适合反序列化为 JSON。这些 classes 没有所需的序列化密钥。
使用这些 classes
data class Response(
@SerializedName("features")
val features: List<Feature>?,
@SerializedName("type")
val type: String?
)
data class Feature(
@SerializedName("geometry")
val geometry: Geometry?,
@SerializedName("properties")
val properties: Properties?,
@SerializedName("type")
val type: String?
)
data class Geometry(
@SerializedName("coordinates")
val coordinates: List<Double>?,
@SerializedName("type")
val type: String?
)
data class Properties(
@SerializedName("description")
val description: String?,
@SerializedName("id")
val id: Int?,
@SerializedName("marker-color")
val markerColor: String?,
@SerializedName("marker-size")
val markerSize: String?,
@SerializedName("occurred_at")
val occurredAt: String?,
@SerializedName("title")
val title: String?
)
要使用 JSON 生成数据 classes,您可以使用 JsonToKotlinClass Android Studio 插件
要反序列化,可以将其视为键值对,键是@serializedName 注释中提供的名称,值是您在其下方提供的数据字段中提供的值。
现在将其与您创建的模型进行比较。
- 首先,您没有为 listme 变量提供任何 @serializedName 注释,它如何知道要在该变量上序列化哪个键的值它应该具有 @serializedName("features") 注释。
- 在“features”键上方的 json 中,我们有键“type”,其值为字符串,因此我们需要另一个变量作为字符串,@serializedName 类型。
- 现在让我们看看您的视频模型 class
其中功能内的值 -> 列表
我们没有任何东西可以序列化模型中 json 中的键“类型”和“属性”,因此使用与 json 响应中相同的键创建适当的模型和变量,正如@Amit pandey[ 回答的那样=18=]
创建合适的模型class
你可以下载插件 Json 到 Kotlin class
当创建一个新的 class 时,单击 alt insert 您将获得将 json 转换为 kotlin class 的选项。
在那里你可以 post 你的 json 响应和你的模型 class 将被创建。
我尝试使用 Retrofit 从响应中获取数据,但我得到的是 空值 。 如果我敬酒响应它总是空但响应显示在日志中但它不是 加载到 Recyclerview
请帮我完成这个面试任务
我的实际反应
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"title": "Stolen 2021 Specialized Sirrus 2.0 (03-14-2021)",
"description": "<img src='https://files.bikeindex.org/uploads/Pu/408280/large_IMG_5771.JPG'> <a target=\"_blank\" href=\"https://bikeindex.org/bikes/1018433\">View details</a>",
"occurred_at": "2021-03-14 22:31:13 -0500",
"marker-size": "small",
"marker-color": "#E74C3C",
"id": 136982
},
"geometry": {
"type": "Point",
"coordinates": [
-122.65,
45.51
]
}
}
ApiClient Class
object ApiClient {
var BASE_URL: String = "https://bikewise.org:443/api/v2/locations/"
val getClient: ApiInterfac
get() {
val gson = GsonBuilder().setLenient().create()
val interceptor = HttpLoggingInterceptor()
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY)
val client = OkHttpClient.Builder().addInterceptor(interceptor).build()
val retrofit = Retrofit.Builder().baseUrl(BASE_URL).client(client).addConverterFactory(GsonConverterFactory.create(gson)).build()
return retrofit.create(ApiInterfac::class.java)
}
}
ApiInterface class:
@GET("markers?proximity=45.521728%2C-122.67326&proximity_square=100")
fun getVideoList(): Call < DataVideos >
}
型号Class
data class DataVideos(
// @SerializedName("type")
var listme:List<Videos>,
@SerializedName("title")
var title:String,
@SerializedName("description")
var description: String)
下面是来自 var listme:List 的视频 Class
class Videos {
@SerializedName("title")
val title: String? = null
@SerializedName("description")
val description: String? = null
}
我的数据变得有趣
private fun getDat1a() {
Log.d(TAG, "GetDataFun")
val call: Call < DataVideos > = ApiClient .getClient.getVideoList()
call.enqueue(object: Callback < DataVideos > {
override fun onResponse(call: Call < DataVideos > ? , response : Response < DataVideos > ? ) {
if(response!!.isSuccessful){
Toast.makeText(activity?.applicationContext!!,"Data:"+response!!.body()!!.listme,Toast.LENGTH_LONG).show()
val rst=response!!.body()
progerssProgressDialog.dismiss()
dataList.addAll(listOf(rst!!))
recyclerView.adapter!!.notifyDataSetChanged()
}
}
override fun onFailure(call: Call < DataVideos> ? , t : Throwable ? ) {
progerssProgressDialog.dismiss()
Log.d(TAG, "Failes"+t)
}
})
}
I'm getting null in Toast as well in recyclerview but in logs i can find the data
我的日志可以显示输出
{"type":"FeatureCollection","features":[{"type":"Feature","properties":{"title":"Stolen 2021 Specialized Sirrus 2.0 (03-14-2021)","description":"\u003cimg src='https://files.bikeindex.org/uploads/Pu/408280/large_IMG_5771.JPG'\u003e \u003ca target=\"_blank\" href=\"https://bikeindex.org/bikes/1018433\"\u003eView details\u003c/a\u003e","occurred_at":"2021-03-14 22:31:13 -0500","marker-size":"small","marker-color":"#E74C3C","id":136982},"geometry":{"type":"Point","coordinates":[-122.65,45.51]}},{"type":"Feature","properties":{"title":"Stolen 2018 Surly Straggler (01-13-2021)","description":"\u003cimg src='https://files.bikeindex.org/uploads/Pu/144946/large_IMG_4383.jpg'\u003e Break in to my garage. \u003ca target=\"_blank\" href=\"https://bikeindex.org/bikes/516282\"\u003eView details\u003c/a\u003e","occurred_at":"2021-01-13 05:00:00 -0600","marker-size":"small","marker-color":"#EE8276","id":134325},"geometry":{"type":"Point","coordinates":[-122.69,45.59]}}]}
2021-03-18 09:26:45.027 7776-8035/com.lab.optisol I/okhttp.OkHttpClient: <-- END HTTP (51772-byte body)
将此模型用于响应
fun getVideoList(): Call<YourResponse>
data class YourResponse(
val type: String? = null,
val features: ArrayList<Features>? = null
)
data class Features(
val type: String? = null,
val properties: Properties? = null,
val geometry:Geometry?=null
)
class Properties(
@SerializedName("title")
@Expose
val title: String? = null,
@SerializedName("description")
@Expose
val description: String? = null,
@SerializedName("occurred_at")
@Expose
val occurred_at: String? = null,
@SerializedName("marker-size")
@Expose
val marker_size: String? = null,
@SerializedName("marker-color")
@Expose
val marker_color: String? = null,
@SerializedName("id")
@Expose
val id: Int? = null
)
data class Geometry(
val type:String?=null,
val coordinates:ArrayList<Double>?=null
)
您的 DataVideo
class 不适合反序列化为 JSON。这些 classes 没有所需的序列化密钥。
使用这些 classes
data class Response(
@SerializedName("features")
val features: List<Feature>?,
@SerializedName("type")
val type: String?
)
data class Feature(
@SerializedName("geometry")
val geometry: Geometry?,
@SerializedName("properties")
val properties: Properties?,
@SerializedName("type")
val type: String?
)
data class Geometry(
@SerializedName("coordinates")
val coordinates: List<Double>?,
@SerializedName("type")
val type: String?
)
data class Properties(
@SerializedName("description")
val description: String?,
@SerializedName("id")
val id: Int?,
@SerializedName("marker-color")
val markerColor: String?,
@SerializedName("marker-size")
val markerSize: String?,
@SerializedName("occurred_at")
val occurredAt: String?,
@SerializedName("title")
val title: String?
)
要使用 JSON 生成数据 classes,您可以使用 JsonToKotlinClass Android Studio 插件
要反序列化,可以将其视为键值对,键是@serializedName 注释中提供的名称,值是您在其下方提供的数据字段中提供的值。
现在将其与您创建的模型进行比较。
- 首先,您没有为 listme 变量提供任何 @serializedName 注释,它如何知道要在该变量上序列化哪个键的值它应该具有 @serializedName("features") 注释。
- 在“features”键上方的 json 中,我们有键“type”,其值为字符串,因此我们需要另一个变量作为字符串,@serializedName 类型。
- 现在让我们看看您的视频模型 class 其中功能内的值 -> 列表 我们没有任何东西可以序列化模型中 json 中的键“类型”和“属性”,因此使用与 json 响应中相同的键创建适当的模型和变量,正如@Amit pandey[ 回答的那样=18=]
创建合适的模型class
你可以下载插件 Json 到 Kotlin class
当创建一个新的 class 时,单击 alt insert 您将获得将 json 转换为 kotlin class 的选项。
在那里你可以 post 你的 json 响应和你的模型 class 将被创建。