In case of Kotlin and coroutines this situation happened when I forgot to mark api service function as suspend
when I call this function from CoroutineScope(Dispatchers.IO).launch{}
:
Usage:
val apiService = RetrofitFactory.makeRetrofitService()
CoroutineScope(Dispatchers.IO).launch {
val response = apiService.myGetRequest()
// process response...
}
ApiService.kt
interface ApiService {
@GET("/my-get-request")
suspend fun myGetRequest(): Response<String>
}
Short answer: return Call<Simple>
in your service interface.
It looks like Retrofit 2.0 is trying to find a way of creating the proxy object for your service interface. It expects you to write this:
public interface SimpleService {
@GET("/simple/{id}")
Call<Simple> getSimple(@Path("id") String id);
}
However, it still wants to play nice and be flexible when you don't want to return a Call
. To support this, it has the concept of a CallAdapter
, which is supposed to know how to adapt a Call<Simple>
into a Simple
.
The use of RxJavaCallAdapterFactory
is only useful if you are trying to return rx.Observable<Simple>
.
The simplest solution is to return a Call
as Retrofit expects. You could also write a CallAdapter.Factory
if you really need it.
add dependencies:
compile 'com.squareup.retrofit:retrofit:2.0.0-beta1'
compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta1'
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta1'
create your adapter this way:
Retrofit rest = new Retrofit.Builder()
.baseUrl(endpoint)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(SimpleXmlConverterFactory.create())
.build();
addCallAdapterFactory ()
and addConverterFactory ()
both need to be called.
Service:
public interface SimpleService {
@GET("/simple/{id}")
Call<Simple> getSimple(@Path("id") String id);
}
Modify Simple
to Call<Simple>
.
With the new Retrofit(2.+) you need to add addCallAdapterFactory which can be a normal one or a RxJavaCallAdapterFactory(for Observables). I think you can add more than both too. It automatically checks which one to use. See a working example below. You can also check this link for more details.
Retrofit retrofit = new Retrofit.Builder().baseUrl(ApiConfig.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build()
If you want use retrofit2
and you don't want always return retrofit2.Call<T>
, you have to create your own CallAdapter.Factory
which return simple type as you expected. The simple code can look like this:
import retrofit2.Call;
import retrofit2.CallAdapter;
import retrofit2.Retrofit;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
public class SynchronousCallAdapterFactory extends CallAdapter.Factory {
public static CallAdapter.Factory create() {
return new SynchronousCallAdapterFactory();
}
@Override
public CallAdapter<Object, Object> get(final Type returnType, Annotation[] annotations, Retrofit retrofit) {
// if returnType is retrofit2.Call, do nothing
if (returnType.toString().contains("retrofit2.Call")) {
return null;
}
return new CallAdapter<Object, Object>() {
@Override
public Type responseType() {
return returnType;
}
@Override
public Object adapt(Call<Object> call) {
try {
return call.execute().body();
} catch (Exception e) {
throw new RuntimeException(e); // do something better
}
}
};
}
}
Then simple register the SynchronousCallAdapterFactory
in Retrofit should solved your problem.
Retrofit rest = new Retrofit.Builder()
.baseUrl(endpoint)
.addConverterFactory(SimpleXmlConverterFactory.create())
.addCallAdapterFactory(SynchronousCallAdapterFactory.create())
.build();
After that you can return simple type without retrofit2.Call
.
public interface SimpleService {
@GET("/simple/{id}")
Simple getSimple(@Path("id") String id);
}
Add the following dependencies for retrofit 2
compile 'com.squareup.retrofit2:retrofit:2.1.0'
for GSON
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
for observables
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
In your case for XML , you would have to include the following dependencies
compile 'com.squareup.retrofit2:converter-simplexml:2.1.0'
Update the service call as below
final Retrofit rest = new Retrofit.Builder()
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(SimpleXmlConverterFactory.create())
.baseUrl(endpoint)
.build();
SimpleService service = rest.create(SimpleService.class);
IllegalArgumentException: Unable to create call adapter for class java.lang.Object
Short answer: I have solved it by the following changes
ext.retrofit2Version = '2.4.0' -> '2.6.0'
implementation"com.squareup.retrofit2:retrofit:$retrofit2Version"
implementation "com.squareup.retrofit2:adapter-rxjava2:$retrofit2Version"
implementation "com.squareup.retrofit2:converter-gson:$retrofit2Version"
Good luck
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With