I'm stuck at Exception that appears in the title. I checked similar topics, but they were specific cases that didn't apply to my situation. Below you could see my models, retrofit setup and its usage. I tried removing Body Class, Response Class, just to check if they are culprits, but unfortunately those weren't the case. Maybe someone will be able to figure out what I'm doing wrong?
Stack Trace:
java.lang.IllegalArgumentException: No Retrofit annotation found. (parameter #2)
for method ApiService.login
at retrofit2.Utils.methodError(Utils.java:52)
at retrofit2.Utils.methodError(Utils.java:42)
at retrofit2.Utils.parameterError(Utils.java:61)
at retrofit2.RequestFactory$Builder.parseParameter(RequestFactory.java:311)
at retrofit2.RequestFactory$Builder.build(RequestFactory.java:182)
at retrofit2.RequestFactory.parseAnnotations(RequestFactory.java:65)
at retrofit2.ServiceMethod.parseAnnotations(ServiceMethod.java:25)
at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:168)
at retrofit2.Retrofit$1.invoke(Retrofit.java:147)
at java.lang.reflect.Proxy.invoke(Proxy.java:1006)
at $Proxy1.login(Unknown Source)
at com.rudearts.cyber2020.services.NetworkService$login$1.invokeSuspend(NetworkService.kt:17)
at com.rudearts.cyber2020.services.NetworkService$login$1.invoke(Unknown Source:10)
at kotlinx.coroutines.flow.SafeFlow.collect(Builders.kt:56)
at kotlinx.coroutines.flow.internal.ChannelFlowOperatorImpl.flowCollect(ChannelFlow.kt:144)
at kotlinx.coroutines.flow.internal.ChannelFlowOperator.collectTo$suspendImpl(ChannelFlow.kt:111)
at kotlinx.coroutines.flow.internal.ChannelFlowOperator.collectTo(Unknown Source:0)
at kotlinx.coroutines.flow.internal.ChannelFlow$collectToFun$1.invokeSuspend(ChannelFlow.kt:33)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:738)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
Models:
import com.google.gson.annotations.SerializedName
data class LoginRequest(
@SerializedName("pin") val pin:String,
@SerializedName("pushId") val pushId:String)
import com.google.gson.annotations.SerializedName
data class UserJson (
@SerializedName("id") val id:Long,
@SerializedName("name") val name:String?,
@SerializedName("access_rights") val accessRights:String?)
Retrofit Builder
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
object RetrofitBuilder {
private const val BASE_URL = "<url>"
private val client = OkHttpClient.Builder().build()
private fun getRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build()
}
val apiService: ApiService = getRetrofit().create(ApiService::class.java)
}
import com.rudearts.cyber2020.model.LoginRequest
import com.rudearts.cyber2020.model.UserJson
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.Headers
import retrofit2.http.POST
interface ApiService {
@Headers("Content-Type: application/json")
@POST("login.php")
suspend fun login(@Body request: LoginRequest):Response<UserJson>
}
Usage in other class:
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import java.util.*
class NetworkService {
private val repoService by lazy { RepoService.instance }
private val apiService = RetrofitBuilder.apiService
fun login(pin:String, token:String): Flow<NetworkResult<Boolean>> = flow {
emit(Loading)
try {
val userJson = apiService.login(LoginRequest(pin,token)).body()
userJson?.let {
val user =
User(userJson.id, userJson.name ?: "", emptyList(), userJson.accessRights ?: "")
repoService.user = user
}
emit(NetworkSuccess(userJson != null))
} catch (throwable: Throwable) {
emit(NetworkError(throwable))
}
}
}
CodePudding user response:
Try call the function like this
fun login(LoginRequest(pin,token))
instead of this
fun login(pin:String, token:String)
the exception says the error is on the second parameter
CodePudding user response:
It could be that you are using an older version of okhttp / retrofit as you are using suspend function it requires the latest version of both libraries.