Reputation: 773
I have the following retrofit singleton:
interface MyAPI
{
@GET("/data.json")
suspend fun fetchData() : Call<MyResponse>
companion object
{
private val BASE_URL = "http://10.0.2.2:8080/"
fun create(): MyAPI
{
val gson = GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
.create()
val retrofit = Retrofit.Builder()
.addConverterFactory( GsonConverterFactory.create( gson ) )
.baseUrl( BASE_URL )
.build()
return retrofit.create( MyAPI::class.java )
}
}
}
MyResponse.kt
data class MyResponse(
val listOfData: List<DataEntity>
)
DataEntity.kt
data class DataEntity(
@SerializedName("name")
val fullName: String
}
I call the code from ModelView the following way:
viewModelScope.launch {
try {
val webResponse = MyAPI.create().fetchData().await()
Log.d( tag, webResponse.toString() )
}
catch ( e : Exception )
{
Log.d( tag, "Exception: " + e.message )
}
}
But I keep getting:
Unable to invoke no-args constructor for retrofit2.Call<com.host.myproject.net.response.MyResponse>. Registering an InstanceCreator with Gson for this type may fix this problem.
I can't seem to find a solution for this problem.. Any hints please?
EDIT:
The JSON response:
[
{
"name": "A"
},
{
"name": "B"
},
{
"name": "C"
}
]
Upvotes: 22
Views: 17879
Reputation: 4912
The problem is that you try to combine suspend
with a Call<T>
return type. When you use suspend
you should make the Retrofit function return the data directly, like this:
suspend fun fetchData() : List<DataEntity> // Note: Not MyResponse, see below
Then all you have to do is to remove .await()
when you make the call, like this:
// Will throw exception unless HTTP 2xx is returned
val webResponse = MyAPI.create().fetchData()
Note that you should not use the MyResponse
class at all since the JSON returns an array directly.
Update:
You can also use Response<DataEntity>
if you need the info from headers
Upvotes: 60
Reputation: 11
if you are using suspend fuction, just remove it
@GET("v1/clients/{client_id}/promocode-info/")
suspend fun getPromoCodeInfo(
@Path("client_id") clientId: String,
@Query("promocode") promoCodeName: String,
): PromoCodeResponse
@GET("v1/clients/{client_id}/promocode-info/")
fun getPromoCodeInfo(
@Path("client_id") clientId: String,
@Query("promocode") promoCodeName: String,
): PromoCodeResponse
Upvotes: 0
Reputation: 316
I have same issue, after checking my model is fine. Then I try to remove suspend on interface API.
@GET("/data.json")
suspend fun fetchData() : Call<MyResponse>
To be
@GET("/data.json")
fun fetchData() : Call<MyResponse>
It solved (the error Unable to invoke no-args constructor for retrofit2.Call has gone).
Upvotes: 7
Reputation: 951
In addition with @Enselic's answer, if you want to get response (for error handling etc.) you can return Response<T> class of Retrofit2 instead of returning data directly. For example,
@POST("/api/news")
@CheckResult
suspend fun getNewsList(
@Body newsRequest: NewsRequest
): Response<NewsResponse>
Upvotes: 2
Reputation: 1540
Step 1: Remove call and handle the response
Before:
@POST("list")
suspend fun requestList(@Body body: JsonObject): call<Profile>
After
@POST("list")
suspend fun requestList(@Body body: JsonObject): Profile
step 2:Remove suspend and handle the response
@POST("list")
fun requestList(@Body body: JsonObject): call<Profile>
Upvotes: 9