在从IllegalArgumentException
(之前)到AsyncTask
(之后)进行最小的更改时,我不断收到错误Kotlin Coroutines
。请注意,代码可以与AsyncTask
一起正常工作。
注意:翻新正在调用我自己的.php
脚本,该脚本返回以SimpleResultObject
字符串编码的某些对象json
。
更改前:
改造:
@FormUrlEncoded
@POST("activity_signup.php")
fun activitySignUp(
@Field("activity_id") activityId: Int,
@Field("user_id") userId: Int) : Call<SimpleResultObject>
活动(在AsyncTask内部):
@Override
protected doInBackground(...) {
val gson = GsonBuilder().setLenient().create()
val retrofit = Retrofit.Builder()
.baseUrl(LOCALHOST_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
val service = retrofit.create(RetrofitAPI::class.java)
val call = service.activitySignUp(activity_id, userId)
call.enqueue(Callback<SimpleResultObject>() {}
通过@onResponse
方法接收对象,然后通常继续进行。
更改后:
改造:
@FormUrlEncoded
@POST("activity_signup.php")
suspend fun activitySignUp(
@Field("activity_id") activityId: Int,
@Field("user_id") userId: Int): SimpleResultObject
活动:
fun signUp() {
myActivityScope.launch(Dispatchers.Main) {
val gson = GsonBuilder().setLenient().create()
val retrofit = Retrofit.Builder()
.baseUrl(LOCALHOST_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
val service = retrofit.create(RetrofitAPI::class.java)
try {
val result = service.activitySignUp(specificResultObject.activityId, userId)
} catch (t:Throwable)
将java.lang.IllegalArgumentException: No Retrofit annotation found. (parameter #3) for method RetrofitAPI.activitySignUp
投向service.activitySignUp
线路呼叫
请注意:myActivityScope
是在托管活动完成时完成的服装CoroutineScope
。
我已经尽我所能记住的一切:添加OkHttpClient
,更改为MoshiConverterFactory
,尝试其他CoroutineScope和Dispatchers,...
编辑:问题可能是由于.php
在我的Exeption
端而引起的,var top = $(this).offset().top - nav_height,
超出了我的参数编号(结果可能为空)?现在。
答案 0 :(得分:1)
基于对问题的回答,我对代码进行了一些修改,并设法解决了该问题。正如@Mohammad Sianaki指出的,最重要的是将Retrofit版本从25.0.0提升到了26.0.0,从而解决了问题。
因此,对于可能在参数编号上方的参数中获得IllegalArgumentException
的其他所有人-考虑检查翻新版本。
特别感谢所有提供帮助的人,尤其是@CommonsWare!
答案 1 :(得分:0)
所提供的代码有一些结构性问题。
首先,似乎正在为每个API调用创建一个改造对象。因此,应为应用程序的所有API调用之一。
第二,网络操作应在非主线程中执行。对于协程,应该在非主要上下文中调用它们,例如Dispatchers.IO
。
第三,我认为您应该在API函数中返回Response<SimpleResultObject>
而不是SimpleResultObject
。
上面假设,我写了一些代码来解决这个问题。因为我认为问题信息中存在一些隐藏因素。
build.gradle
dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.6.1'
implementation 'com.squareup.retrofit2:converter-gson:2.6.1'
implementation 'com.squareup.okhttp3:logging-interceptor:3.14.1'
implementation 'com.squareup.okhttp3:okhttp-urlconnection:3.14.1'
implementation 'com.squareup.okhttp3:okhttp:3.14.1'
}
RetrofitAPI.kt
import retrofit2.Response
import retrofit2.http.Field
import retrofit2.http.FormUrlEncoded
import retrofit2.http.POST
interface RetrofitAPI {
@FormUrlEncoded
@POST("activity_signup.php")
suspend fun activitySignUp(
@Field("activity_id") activityId: Int,
@Field("user_id") userId: Int
): Response<SimpleResultObject>
// Other api declarations ...
}
BaseApiManager.kt
import okhttp3.JavaNetCookieJar
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.net.CookieManager
import java.util.concurrent.TimeUnit
abstract class BaseApiManager(endPoint: String) {
protected val retrofitAPI: RetrofitAPI =
createAdapter(endPoint)
.create(RetrofitAPI::class.java)
private fun createAdapter(choice: String): Retrofit {
return Retrofit.Builder()
.baseUrl(choice)
.client(createHttpClient())
.addConverterFactory(GsonConverterFactory.create()).build()
}
companion object {
private fun createHttpClient(): OkHttpClient {
val httpClient: OkHttpClient.Builder = OkHttpClient.Builder()
val cookieHandler = CookieManager()
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
httpClient.interceptors().add(interceptor)
httpClient.cookieJar(JavaNetCookieJar(cookieHandler))
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
return httpClient.build()
}
}
}
ApiManager.kt
private const val API_END_POINT = "https://your.webservice.endpoint/"
object ApiManager : BaseApiManager(API_END_POINT) {
suspend fun activitySignUp(
activityId: Int,
userId: Int
) = retrofitAPI.activitySignUp(activityId, userId)
// Other api implementations ...
}
fun signUp() {
myActivityScope.launch(Dispatchers.IO) {
ApiManager.activitySignUp(activityId, userId).also { response ->
when {
response.isSuccessful -> {
val result = response.body()
result?.apply {
// do something with the result
}
}
else -> {
val code = response.code()
val message = response.message()
// do something with the error parameters...
}
}
}
}
}