使用Retrofit的@PartMap进行多部分请求时出现Kotlin(Android)错误

20

如果我在Java中使用此代码,则正常工作。当我将该代码转换为kotlin时,就会出现错误。

日志

08-20 23:46:51.003 3782-3782/com.qkangaroo.app W/System.err: java.lang.IllegalArgumentException: 参数类型不得包含类型变量或通配符:java.util.Map(参数#1) 08-20 23:46:51.003 3782-3782/com.qkangaroo.app W/System.err: 在方法ApiInterface.updateCustomerDetail中 08-20 23:46:51.003 3782-3782/com.qkangaroo.app W/System.err: retrofit2.ServiceMethod$Builder.methodError(ServiceMethod.java:752) 08-20 23:46:51.004 3782-3782/com.qkangaroo.app W/System.err: retrofit2.ServiceMethod$Builder.methodError(ServiceMethod.java:743) 08-20 23:46:51.004 3782-3782/com.qkangaroo.app W/System.err: retrofit2.ServiceMethod$Builder.parameterError(ServiceMethod.java:761) 08-20 23:46:51.004 3782-3782/com.qkangaroo.app W/System.err: retrofit2.ServiceMethod$Builder.build(ServiceMethod.java:195) 08-20 23:46:51.004 3782-3782/com.qkangaroo.app W/System.err: retrofit2.Retrofit.loadServiceMethod(Retrofit.java:170) 08-20 23:46:51.005 3782-3782/com.qkangaroo.app W/System.err: retrofit2.Retrofit$1.invoke(Retrofit.java:147) 08-20 23:46:51.005 3782-3782/com.qkangaroo.app W/System.err: $Proxy0.updateCustomerDetail(Native Method) 08-20 23:46:51.005 3782-3782/com.qkangaroo.app W/System.err: com.qkangaroo.app.Fragments.MoreScreen.MoreFragment.updateProfile(MoreFragment.kt:261) 08-20 23:46:51.006 3782-3782/com.qkangaroo.app W/System.err: com.qkangaroo.app.Fragments.MoreScreen.MoreFragment$clickListener$1.onClick(MoreFragment.kt:191) 08-20 23:46:51.006 3782-3782/com.qkangaroo.app W/System.err: android.view.View.performClick(View.java:3517) 08-20 23:46:51.006 3782-3782/com.qkangaroo.app W/System.err: android.view.View$PerformClick.run(View.java:14155) 08-20 23:46:51.006 3782-3782/com.qkangaroo.app W/System.err: android.os.Handler.handleCallback(Handler.java:605) 08-20 23:46:51.007 3782-3782/com.qkangaroo.app W/System.err: android.os.Handler.dispatchMessage(Handler.java:92) 08-20 23:46:51.007 3782-3782/com.qkangaroo.app W/System.err: android.os.Looper.loop(Looper.java:154) 08-20 23:46:51.007 3782-3782/com.qkangaroo.app W/System.err: android.app.ActivityThread.main(ActivityThread.java:4624) 08-20 23:46:51.008 3782-3782/com.qkangaroo.app W/System.err: java.lang.reflect.Method.invokeNative(Native Method) 08-20 23:46:51.009 3782-3782/com.qkangaroo.app W/System.err: java.lang.reflect.Method.invoke(Method.java:511) 08-20 23:46:51.009 3782-3782/com.qkangaroo.app W/System.err: com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:809) 08-20 23:46:51.010 3782-3782/com.qkangaroo.app W/System.err: com.android.internal.os.ZygoteInit.main(ZygoteInit.java:576) 08-20 23:46:51.011 3782-3782/com.qkangaroo.app W/System.err: 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)
}

ApiInterface,.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"

2
使用fun updateCustomerDetail(@PartMap map: Map<String, @JvmSuppressWildcards RequestBody >): Call<UpdateCustomer>进行客户详情更新。 - Orkhan Alikhanov
它对我有效。谢谢。 - Jagnesh Chawla
3个回答

63

RequestBody之前添加@JvmSuppressWildcards

fun updateCustomerDetail(@PartMap map: Map<String, @JvmSuppressWildcards RequestBody >): Call<UpdateCustomer>

11
你想通过添加一些解释来改善你的仅代码答案吗? - Yunnosch
@JagneshChawla 谢谢!!!!!太感谢了伙计...你的回答刚好解决了我的问题。 - MashukKhan
@JagneshChawla 你能否解释一下这个问题,如何以及为什么? - P Vartak
1
@PVartak https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html#variant-generics - Jagnesh Chawla

21

使用HashMapMutableMap代替Map< K, out V>作为PartMap的替代方案。

一种替代方式对我很有效。alex-tpom6ohRetrofi Kotlin Issue中提到过。

我认为这是因为Map声明为public interface Map< K, out V>,out关键字使值类型变成了泛型。你可以尝试使用MutableMapHashMap代替。

@Multipart
@POST("customer")
fun updateCustomerDetail(@PartMap map: HashMap<String, RequestBody>): Call<UpdateCustomer>

0

你可以使用 JsonObject 来进行转换,就像这样:

  1. 在你的 ApiService 类中
@Headers("Content-Type: application/json")
@POST(EndPoints)
fun apiName(
    @Body body: JsonObject
): Call<ResponseBody>

并在你的主类中像这样传递:
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);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接