浏览代码

fix: #165 泛型擦除

drake 2 年之前
父节点
当前提交
57e7a55062

+ 0 - 3
net/src/main/java/com/drake/net/reflect/TypeUtil.kt

@@ -1,3 +0,0 @@
-package com.drake.net.reflect
-
-inline fun <reified R> typeTokenOf() = object : TypeToken<R>() {}.type

+ 7 - 0
net/src/main/java/com/drake/net/reflect/TypeUtils.kt

@@ -0,0 +1,7 @@
+package com.drake.net.reflect
+
+import kotlin.reflect.javaType
+import kotlin.reflect.typeOf
+
+@OptIn(ExperimentalStdlibApi::class)
+inline fun <reified T> typeTokenOf() = typeOf<T>().javaType

+ 8 - 5
net/src/main/java/com/drake/net/request/BaseRequest.kt

@@ -24,15 +24,17 @@ import com.drake.net.convert.NetConverter
 import com.drake.net.exception.URLParseException
 import com.drake.net.interfaces.ProgressListener
 import com.drake.net.okhttp.toNetOkhttp
+import com.drake.net.reflect.TypeToken
+import com.drake.net.reflect.typeTokenOf
 import com.drake.net.response.convert
 import com.drake.net.tag.NetTag
 import okhttp3.*
 import okhttp3.HttpUrl.Companion.toHttpUrl
 import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
 import java.io.File
+import java.lang.reflect.Type
 import java.net.URL
 import java.util.concurrent.TimeUnit
-import kotlin.reflect.KType
 import kotlin.reflect.typeOf
 
 abstract class BaseRequest {
@@ -440,14 +442,15 @@ abstract class BaseRequest {
         setKType<R>()
         val request = buildRequest()
         val newCall = okHttpClient.newCall(request)
-        return newCall.execute().convert(R::class.java)
+        return newCall.execute().convert()
     }
 
     /**
      * 执行同步请求
-     * 本方法不会为请求默认添加[KType], 支持Java调用
+     * 本方法仅为兼容Java使用存在
+     * @param type 如果存在泛型嵌套要求使用[typeTokenOf]或者[TypeToken]获取, 否则泛型会被擦除导致无法解析
      */
-    fun <R> execute(type: Class<R>): R {
+    fun <R> execute(type: Type): R {
         NetConfig.requestInterceptor?.interceptor(this)
         val request = buildRequest()
         val newCall = okHttpClient.newCall(request)
@@ -464,7 +467,7 @@ abstract class BaseRequest {
         val request = buildRequest()
         val newCall = okHttpClient.newCall(request)
         return try {
-            val value = newCall.execute().convert<R>(R::class.java)
+            val value = newCall.execute().convert<R>()
             Result.success(value)
         } catch (e: Exception) {
             Result.failure(e)

+ 19 - 0
net/src/main/java/com/drake/net/response/ResponseExtension.kt

@@ -20,6 +20,8 @@ import com.drake.net.component.Progress
 import com.drake.net.exception.ConvertException
 import com.drake.net.exception.DownloadFileException
 import com.drake.net.exception.NetException
+import com.drake.net.reflect.TypeToken
+import com.drake.net.reflect.typeTokenOf
 import com.drake.net.request.*
 import com.drake.net.tag.NetTag
 import com.drake.net.utils.md5
@@ -149,6 +151,23 @@ fun Response.file(): File? {
  */
 @Suppress("UNCHECKED_CAST")
 @Throws(IOException::class)
+inline fun <reified R> Response.convert(): R {
+    try {
+        return request.converter().onConvert<R>(typeTokenOf<R>(), this) as R
+    } catch (e: NetException) {
+        throw e
+    } catch (e: Throwable) {
+        throw ConvertException(this, cause = e)
+    }
+}
+
+/**
+ * 响应体使用转换器处理数据
+ * 本方法仅为兼容Java使用存在
+ * @param type 如果存在泛型嵌套要求使用[typeTokenOf]或者[TypeToken]获取, 否则泛型会被擦除导致无法解析
+ */
+@Suppress("UNCHECKED_CAST")
+@Throws(IOException::class)
 fun <R> Response.convert(type: Type): R {
     try {
         return request.converter().onConvert<R>(type, this) as R

+ 2 - 0
sample/src/main/java/com/drake/net/sample/constants/Api.kt

@@ -7,4 +7,6 @@ object Api {
     const val DELAY = "/delay"
     const val UPLOAD = "/upload"
     const val GAME = "/game"
+    const val DATA = "/data"
+    const val ARRAY = "/array"
 }

+ 2 - 0
sample/src/main/java/com/drake/net/sample/mock/MockDispatcher.kt

@@ -55,6 +55,8 @@ class MockDispatcher : Dispatcher() {
             Api.DELAY -> MockResponse().setBodyDelay(2, TimeUnit.SECONDS).setHeader("Content-Type", "text/plain").setBody("Request Success : ${request.method}")
             Api.UPLOAD -> MockResponse().setBodyDelay(1, TimeUnit.SECONDS).setHeader("Content-Type", "text/plain").setBody("Upload Success")
             Api.GAME -> getRawResponse(R.raw.game)
+            Api.DATA -> getRawResponse(R.raw.data)
+            Api.ARRAY -> getRawResponse(R.raw.array)
             else -> MockResponse().setResponseCode(404)
         }
     }

+ 22 - 0
sample/src/main/java/com/drake/net/sample/model/ArrayData.kt

@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2018 Drake, https://github.com/liangjingkanji
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.drake.net.sample.model
+
+class ArrayData {
+    var title: String = ""
+    var name: String = ""
+}

+ 23 - 0
sample/src/main/java/com/drake/net/sample/model/BasicData.kt

@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2018 Drake, https://github.com/liangjingkanji
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.drake.net.sample.model
+
+open class BasicData<T> {
+    val code: String = ""
+    val msg: String = ""
+    val data: T? = null
+}

+ 22 - 0
sample/src/main/java/com/drake/net/sample/model/SubData.kt

@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2018 Drake, https://github.com/liangjingkanji
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.drake.net.sample.model
+
+class SubData : BasicData<SubData>() {
+    var title: String = ""
+    var name: String = ""
+}

+ 18 - 0
sample/src/main/res/raw/array.json

@@ -0,0 +1,18 @@
+[
+  {
+    "title": "标题",
+    "name": "名称"
+  },
+  {
+    "title": "标题",
+    "name": "名称"
+  },
+  {
+    "title": "标题",
+    "name": "名称"
+  },
+  {
+    "title": "标题",
+    "name": "名称"
+  }
+]

+ 8 - 0
sample/src/main/res/raw/data.json

@@ -0,0 +1,8 @@
+{
+  "code": 0,
+  "msg": "OK",
+  "data": {
+    "title": "标题",
+    "name": "名称"
+  }
+}