Kotlin 中 Retrofit @PartMap 错误的多部分请求 (Android)
Multipart request with Retrofit @PartMap Error in Kotlin (Android)
如果我在 Java 中使用此代码,那么它工作正常。当我在 kotlin 中转换该代码时出现错误。
Logcat
08-20 23:46:51.003 3782-3782/com.qkangaroo.app W/System.err: java.lang.IllegalArgumentException: Parameter type must not include a type variable or wildcard: java.util.Map (parameter #1)
08-20 23:46:51.003 3782-3782/com.qkangaroo.app W/System.err: for method ApiInterface.updateCustomerDetail
08-20 23:46:51.003 3782-3782/com.qkangaroo.app W/System.err: at retrofit2.ServiceMethod$Builder.methodError(ServiceMethod.java:752)
08-20 23:46:51.004 3782-3782/com.qkangaroo.app W/System.err: at retrofit2.ServiceMethod$Builder.methodError(ServiceMethod.java:743)
08-20 23:46:51.004 3782-3782/com.qkangaroo.app W/System.err: at retrofit2.ServiceMethod$Builder.parameterError(ServiceMethod.java:761)
08-20 23:46:51.004 3782-3782/com.qkangaroo.app W/System.err: at retrofit2.ServiceMethod$Builder.build(ServiceMethod.java:195)
08-20 23:46:51.004 3782-3782/com.qkangaroo.app W/System.err: at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:170)
08-20 23:46:51.005 3782-3782/com.qkangaroo.app W/System.err: at retrofit2.Retrofit.invoke(Retrofit.java:147)
08-20 23:46:51.005 3782-3782/com.qkangaroo.app W/System.err: at $Proxy0.updateCustomerDetail(Native Method)
08-20 23:46:51.005 3782-3782/com.qkangaroo.app W/System.err: at com.qkangaroo.app.Fragments.MoreScreen.MoreFragment.updateProfile(MoreFragment.kt:261)
08-20 23:46:51.006 3782-3782/com.qkangaroo.app W/System.err: at com.qkangaroo.app.Fragments.MoreScreen.MoreFragment$clickListener.onClick(MoreFragment.kt:191)
08-20 23:46:51.006 3782-3782/com.qkangaroo.app W/System.err: at android.view.View.performClick(View.java:3517)
08-20 23:46:51.006 3782-3782/com.qkangaroo.app W/System.err: at android.view.View$PerformClick.run(View.java:14155)
08-20 23:46:51.006 3782-3782/com.qkangaroo.app W/System.err: at android.os.Handler.handleCallback(Handler.java:605)
08-20 23:46:51.007 3782-3782/com.qkangaroo.app W/System.err: at android.os.Handler.dispatchMessage(Handler.java:92)
08-20 23:46:51.007 3782-3782/com.qkangaroo.app W/System.err: at android.os.Looper.loop(Looper.java:154)
08-20 23:46:51.007 3782-3782/com.qkangaroo.app W/System.err: at android.app.ActivityThread.main(ActivityThread.java:4624)
08-20 23:46:51.008 3782-3782/com.qkangaroo.app W/System.err: at java.lang.reflect.Method.invokeNative(Native Method)
08-20 23:46:51.009 3782-3782/com.qkangaroo.app W/System.err: at java.lang.reflect.Method.invoke(Method.java:511)
08-20 23:46:51.009 3782-3782/com.qkangaroo.app W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:809)
08-20 23:46:51.010 3782-3782/com.qkangaroo.app W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:576)
08-20 23:46:51.011 3782-3782/com.qkangaroo.app W/System.err: at dalvik.system.NativeStart.main(Native Method)
fragment.kt
var map:HashMap<String,RequestBody> = HashMap<String, RequestBody>()
map.put("version",ApiClient.createRequestBody(AppConstants.API_VERSION))
map.put("auth_token", ApiClient.createRequestBody(customer.authToken!!))
map.put("customer_name",ApiClient.createRequestBody(profileName))
map.put("email", ApiClient.createRequestBody(profileEmail))
val apiInterface = ApiClient.client.create(ApiInterface::class.java)
val updateCustomerCall: Call<UpdateCustomer> = apiInterface.updateCustomerDetail(map)
updateCustomerCall.enqueue(object : Callback<UpdateCustomer> {
override fun onResponse(call: Call<UpdateCustomer>?, response: Response<UpdateCustomer>?) {
}
override fun onFailure(call: Call<UpdateCustomer>?, t: Throwable?) {
utilities!!.hideProgress(progress)
}
})
ApiClient.kt
val MULTIPART_FORM_DATA = "multipart/form-data"
fun createRequestBody(s: String): RequestBody {
return RequestBody.create(
MediaType.parse(MULTIPART_FORM_DATA), s)
}
Api接口,.kt
@Multipart
@POST("customer")
fun updateCustomerDetail(@PartMap map: Map<String,RequestBody >): Call<UpdateCustomer>
Gradle 文件
implementation "com.squareup.okhttp3:okhttp:3.8.1"
implementation "com.squareup.okhttp3:logging-interceptor:3.8.1"
implementation ("com.squareup.retrofit2:retrofit:2.3.0"){
exclude module: 'okhttp'
}
implementation "com.squareup.retrofit2:converter-gson:2.3.0"
在RequestBody
前添加@JvmSuppressWildcards
fun updateCustomerDetail(@PartMap map: Map<String, @JvmSuppressWildcards RequestBody >): Call<UpdateCustomer>
使用HashMap或MutableMap代替Map 零件图
另一种方法对我来说效果很好。 alex-tpom6oh in Retrofi Kotlin Issue
提到
I think it's happening because the Map declaration is public interface Map< K, out V> and the out word makes the value type generic. You can try to use MutableMap or HashMap instead.
@Multipart
@POST("customer")
fun updateCustomerDetail(@PartMap map: HashMap<String, RequestBody>): Call<UpdateCustomer>
您可以使用 JsonObject 进行转换,就像这样:
- 在您的 ApiService 中 Class
@Headers("Content-Type: application/json")
@POST(EndPoints)
fun apiName(
@Body body: JsonObject
): Call<ResponseBody>
- 然后在你的 Main 中像这样传递 Class
JsonObject body = new JsonObject();
body.addProperty("key", "value");
body.addProperty("key", "value");
ApiInterface apiInterface = APIClient.getClient().create(ApiService.class);
Call<ResponseBody> call = apiInterface.follow(body);
如果我在 Java 中使用此代码,那么它工作正常。当我在 kotlin 中转换该代码时出现错误。
Logcat
08-20 23:46:51.003 3782-3782/com.qkangaroo.app W/System.err: java.lang.IllegalArgumentException: Parameter type must not include a type variable or wildcard: java.util.Map (parameter #1) 08-20 23:46:51.003 3782-3782/com.qkangaroo.app W/System.err: for method ApiInterface.updateCustomerDetail 08-20 23:46:51.003 3782-3782/com.qkangaroo.app W/System.err: at retrofit2.ServiceMethod$Builder.methodError(ServiceMethod.java:752) 08-20 23:46:51.004 3782-3782/com.qkangaroo.app W/System.err: at retrofit2.ServiceMethod$Builder.methodError(ServiceMethod.java:743) 08-20 23:46:51.004 3782-3782/com.qkangaroo.app W/System.err: at retrofit2.ServiceMethod$Builder.parameterError(ServiceMethod.java:761) 08-20 23:46:51.004 3782-3782/com.qkangaroo.app W/System.err: at retrofit2.ServiceMethod$Builder.build(ServiceMethod.java:195) 08-20 23:46:51.004 3782-3782/com.qkangaroo.app W/System.err: at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:170) 08-20 23:46:51.005 3782-3782/com.qkangaroo.app W/System.err: at retrofit2.Retrofit.invoke(Retrofit.java:147) 08-20 23:46:51.005 3782-3782/com.qkangaroo.app W/System.err: at $Proxy0.updateCustomerDetail(Native Method) 08-20 23:46:51.005 3782-3782/com.qkangaroo.app W/System.err: at com.qkangaroo.app.Fragments.MoreScreen.MoreFragment.updateProfile(MoreFragment.kt:261) 08-20 23:46:51.006 3782-3782/com.qkangaroo.app W/System.err: at com.qkangaroo.app.Fragments.MoreScreen.MoreFragment$clickListener.onClick(MoreFragment.kt:191) 08-20 23:46:51.006 3782-3782/com.qkangaroo.app W/System.err: at android.view.View.performClick(View.java:3517) 08-20 23:46:51.006 3782-3782/com.qkangaroo.app W/System.err: at android.view.View$PerformClick.run(View.java:14155) 08-20 23:46:51.006 3782-3782/com.qkangaroo.app W/System.err: at android.os.Handler.handleCallback(Handler.java:605) 08-20 23:46:51.007 3782-3782/com.qkangaroo.app W/System.err: at android.os.Handler.dispatchMessage(Handler.java:92) 08-20 23:46:51.007 3782-3782/com.qkangaroo.app W/System.err: at android.os.Looper.loop(Looper.java:154) 08-20 23:46:51.007 3782-3782/com.qkangaroo.app W/System.err: at android.app.ActivityThread.main(ActivityThread.java:4624) 08-20 23:46:51.008 3782-3782/com.qkangaroo.app W/System.err: at java.lang.reflect.Method.invokeNative(Native Method) 08-20 23:46:51.009 3782-3782/com.qkangaroo.app W/System.err: at java.lang.reflect.Method.invoke(Method.java:511) 08-20 23:46:51.009 3782-3782/com.qkangaroo.app W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:809) 08-20 23:46:51.010 3782-3782/com.qkangaroo.app W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:576) 08-20 23:46:51.011 3782-3782/com.qkangaroo.app W/System.err: at dalvik.system.NativeStart.main(Native Method)
fragment.kt
var map:HashMap<String,RequestBody> = HashMap<String, RequestBody>()
map.put("version",ApiClient.createRequestBody(AppConstants.API_VERSION))
map.put("auth_token", ApiClient.createRequestBody(customer.authToken!!))
map.put("customer_name",ApiClient.createRequestBody(profileName))
map.put("email", ApiClient.createRequestBody(profileEmail))
val apiInterface = ApiClient.client.create(ApiInterface::class.java)
val updateCustomerCall: Call<UpdateCustomer> = apiInterface.updateCustomerDetail(map)
updateCustomerCall.enqueue(object : Callback<UpdateCustomer> {
override fun onResponse(call: Call<UpdateCustomer>?, response: Response<UpdateCustomer>?) {
}
override fun onFailure(call: Call<UpdateCustomer>?, t: Throwable?) {
utilities!!.hideProgress(progress)
}
})
ApiClient.kt
val MULTIPART_FORM_DATA = "multipart/form-data"
fun createRequestBody(s: String): RequestBody {
return RequestBody.create(
MediaType.parse(MULTIPART_FORM_DATA), s)
}
Api接口,.kt
@Multipart
@POST("customer")
fun updateCustomerDetail(@PartMap map: Map<String,RequestBody >): Call<UpdateCustomer>
Gradle 文件
implementation "com.squareup.okhttp3:okhttp:3.8.1"
implementation "com.squareup.okhttp3:logging-interceptor:3.8.1"
implementation ("com.squareup.retrofit2:retrofit:2.3.0"){
exclude module: 'okhttp'
}
implementation "com.squareup.retrofit2:converter-gson:2.3.0"
在RequestBody
@JvmSuppressWildcards
fun updateCustomerDetail(@PartMap map: Map<String, @JvmSuppressWildcards RequestBody >): Call<UpdateCustomer>
使用HashMap或MutableMap代替Map
另一种方法对我来说效果很好。 alex-tpom6oh in Retrofi Kotlin Issue
提到I think it's happening because the Map declaration is public interface Map< K, out V> and the out word makes the value type generic. You can try to use MutableMap or HashMap instead.
@Multipart
@POST("customer")
fun updateCustomerDetail(@PartMap map: HashMap<String, RequestBody>): Call<UpdateCustomer>
您可以使用 JsonObject 进行转换,就像这样:
- 在您的 ApiService 中 Class
@Headers("Content-Type: application/json")
@POST(EndPoints)
fun apiName(
@Body body: JsonObject
): Call<ResponseBody>
- 然后在你的 Main 中像这样传递 Class
JsonObject body = new JsonObject();
body.addProperty("key", "value");
body.addProperty("key", "value");
ApiInterface apiInterface = APIClient.getClient().create(ApiService.class);
Call<ResponseBody> call = apiInterface.follow(body);