IllegalArgumentException: Could not locate call adapter for rx.Observable RxJava, Retrofit2 - android

I am getting the above error while calling the rest api. I am using both retrofit2 and RxJava.
ServiceFactory.java
public class ServiceFactory {
public static <T> T createRetrofitService(final Class<T> clazz, final String endpoint){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(endpoint)
//.addConverterFactory(GsonConverterFactory.create())
.build();
T service = retrofit.create(clazz);
return service;
}
}
MovieService.java
public interface MovieService{
//public final String API_KEY = "<apikey>";
public final String SERVICE_END = "https://api.mymovies.org/3/";
#GET("movie/{movieId}??api_key=xyz")
Observable<Response<Movies>> getMovies(#Field("movieId") int movieId);
}
Inside MainActivity
MovieService tmdbService = ServiceFactory.createRetrofitService(MovieService.class, MovieService.SERVICE_END);
Observable<Response<Movies>> responseObservable = tmdbService.getMovies(400);
responseObservable .subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Response<Movies>>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
}
#Override
public void onNext(Response<Movies> moviesResponse) {
}
});

Be sure to add implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0' or whatever version you are using to your dependencies, and then configure retrofit with that converter:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(endpoint)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
Updated
RxJavaCallAdapterFactory was renamed to RxJava2CallAdapterFactory. Changed the snipped above.

For RxJava2 Use compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
For more information on usage https://github.com/JakeWharton/retrofit2-rxjava2-adapter

you should have to use all Rx dependency of latest version , here i am using version 2 (like rxjava2)
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
implementation 'io.reactivex.rxjava2:rxjava:2.1.9'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
And add one more thing :
addCallAdapterFactory(RxJava2CallAdapterFactory.create())
in Retrofit Api client
like :
retrofit = new Retrofit.Builder()
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(BASE_URL)
.build();

From the said Github project page:
Blockquote
This is now DEPRECATED!
Retrofit 2.2 and newer have a first-party call adapter for RxJava 2: https://github.com/square/retrofit/tree/master/retrofit-adapters/rxjava2
now you just need to include in your app/build.gradle file:
compile 'com.squareup.retrofit2:adapter-rxjava2:latest.version'

In my case, it was enough to replace
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
with
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())

Related

Unable to create call adapter for io.reactivex.Single

I want to conncet to server with retrofit and rxjava.it works when I used call and everything is good.but when try to use rxjava ,its getsinto trouble.
the error text:
Could not locate call adapter for io.reactivex.Single
in the build.gradle I implemented the retrofit adapter.but I dont know whats the problem.
this is my gradle:
implementation 'com.squareup.picasso:picasso:2.71828'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
implementation 'io.reactivex.rxjava2:rxjava:2.2.8'
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.retrofit2:adapter-rxjava:2.5.0'
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
implementation "android.arch.persistence.room:runtime:1.1.1"
annotationProcessor "android.arch.persistence.room:compiler:1.1.1"
api client code:
public class ApiClient {
public static final String BASE_URL="http://192.168.1.100/digikala/";
private static Retrofit retrofit=null;
public static Retrofit getClient(){
if(retrofit==null){
retrofit=new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.baseUrl(BASE_URL)
.build();
}
return retrofit;
}
api service code:
public interface ApiService {
#GET("readamazing.php")
Single<List<Product>> getSingleProducts();
}
main acitivity code:
ApiService apiService=ApiClient.getClient().create(ApiService.class);
apiService.getSingleProducts().subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new SingleObserver<List<Product>>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onSuccess(List<Product> products) {
Log.i("LOG", "onSuccess: "+products.toString());
}
#Override
public void onError(Throwable e) {
Log.i("LOG", "onSuccess: "+e.toString());
}
});
Use RxJava2CallAdapterFactory instead of RxJavaCallAdapterFactory as RxJava2 is used.
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
to the Retrofit.Builder().

How can I debug my retrofit API call?

I'm using retrofit to get some data from the Flickr api. The method I'm making the call in looks like this:
public static List<String> getImageIds(int size) {
Call<PhotosList> call = flickrService.getPhotos(apiKey, format, "1");
Log.d("TEMP_TAG", "photo url: " + call.request().url().toString());
photoIds = new ArrayList<String>();
call.enqueue(new Callback<PhotosList>(){
#Override
public void onResponse(Call<PhotosList> call, Response<PhotosList> response) {
Log.d("TEMP_TAG", "it's getting here");
PhotosList photosList = response.body();
List<Photo> photos = photosList.getPhotos().getPhoto();
for(Photo photo : photos) {
Log.d("TEMP_TAG", "adding photo id to list: " + photo.getId());
photoIds.add(photo.getId());
}
}
#Override
public void onFailure(Call<PhotosList> call, Throwable t) {
// TODO: Clean up
Log.d("TEMP_TAG", "photoId: ");
}
});
Log.d("TEMP_TAG", "it's getting here too");
return photoIds;
}
However it is never getting into the onResponse() method. The first log statement within onResponse() never prints, neither does the log statement in onFailure(). When I try entering the URL that is returned by call.request().url().toString() in the browser it works fine, and I get the expected JSON. Why is my enqueue() method never firing?
Thanks for any help!
Use HttpLoggingInterceptor along with Retrofit.
If this helps, add this inside your build.gradle -
//Retrofit and OkHttp for Networking
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
//Logging Network Calls
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.1'
Inside your APIClient class add this -
public class ApiClient {
private static Retrofit retrofit = null;
public static Retrofit getClient(){
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.build();
if(retrofit==null){
retrofit = new Retrofit.Builder()
.baseUrl(BuildConfig.baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
}
return retrofit;
}
}
Kotlin Code
val interceptor : HttpLoggingInterceptor = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
val client : OkHttpClient = OkHttpClient.Builder().apply {
addInterceptor(interceptor)
}.build()
fun getService(): Service {
return Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(LiveDataCallAdapterFactory())
.client(client)
.build()
.create(Service::class.java)
}
And you will be able to log the Retrofit Network calls that you make.
Let me know if you need more information.
An OkHttp interceptor which logs HTTP request and response data.
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(Level.BASIC);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(logging)
.build();
You can change the log level at any time by calling setLevel.
There are 4 levels: NONE, BASIC, HEADERS, BODY
To log to a custom location, pass a Logger instance to the constructor.
HttpLoggingInterceptor logging = new HttpLoggingInterceptor(new
Logger() {
#Override public void log(String message) {
Log.d(TAG, "message: ");
}
});
From Gradle
compile 'com.squareup.okhttp3:logging-interceptor:(insert latest version)'
Follow this reference
EDITED: I also found this library which has a very nice structure and clean log. Try it!!
You can use the following class to log API calls
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
object HTTPLogger {
fun getLogger(): OkHttpClient {
/*
* OKHTTP interceptor to log all API calls
*/
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
val client = OkHttpClient.Builder()
.addInterceptor(interceptor)
.build()
return client
}
}
You can then call this class in your retrofit instance class like this
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
object RetrofitClientInstance {
private var retrofit: Retrofit? = null
val retrofitInstance: Retrofit?
get() {
if (retrofit == null) {
retrofit = Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(HTTPLogger.getLogger())
.build()
}
return retrofit
}
}
The dependency required is
implementation 'com.squareup.okhttp3:logging-interceptor:3.9.0'

Retrofit is not making api call

I'm using retrofit 2 to make api call to my server but it get stucked when trying to make api call. This is my code
public interface GOTApi {
#GET("characters.json")
Call<GOTCharacterResponse> getCharacters();
}
Intermediate class to get the data
public class GOTCharacterResponse {
List<GOTCharacter> characters;
}
My class to make api call
public class GOTService {
public static final String BASE_URL = "https://project-8424324399725905479.firebaseio.com/";
public static GOTApi getGOTApi(){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
return retrofit.create(GOTApi.class);
}
public static void getCharacters(){
getGOTApi().getCharacters().enqueue(new Callback<GOTCharacterResponse>() {
#Override
public void onResponse(Call<GOTCharacterResponse> call, Response<GOTCharacterResponse> response) {
if(response.isSuccessful()){
}
}
#Override
public void onFailure(Call<GOTCharacterResponse> call, Throwable t) {
int a = 0;
}
});
}
}
These are the libraries I'm using
compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'
compile 'com.squareup.okhttp3:okhttp:3.3.1'
It always get stucked in the getCharacters() method. Of course I have internet permission set in Mainfest.
You may try using Retrofit2 with RxJava, it is more convenient.
public Retrofit providedRetrofit(OkHttpClient okHttpClient){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BuildConfig.BASE_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
return retrofit;
}
Your API interface will look like
public interface Api {
#GET("api/service/schedule/{filial}")
Observable<Response<GOTCharacter>> getSchedule(#Path("some_param") String param);
}
You also need to parse response from JSON. You didn't provided
GOTCharacter class, but you can create code from json response by using
http://www.jsonschema2pojo.org/ service
I think you are implementing wrong onResponse() OR Callback(), because I am using Retrofit 2 too, in which onResponse() looks like this:
#Override
public void onResponse(Response<ListJsonResponseRestaurant> response, Retrofit retrofit) {
...
...
}

apply url to retrofit

I'm writting a retrofit demo.
I have to use "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code" to get code.
when writing rest, I do it like this:
public interface WXService {
#GET("/access_token?grant_type=authorization_code")
Observable<AccessTokenModel> getAccessToken(#Query("appid") String appId,
#Query("secret") String secretId,
#Query("code") String code);
}
public class WXRest {
private static final String WXBaseUrl = "https://api.weixin.qq.com/sns/oauth2/";
private WXService mWXService;
public WXRest() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(WXBaseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
mWXService = retrofit.create(WXService.class);
}
public void getAccessToken(String code) {
mWXService.getAccessToken(Constants.APP_ID, Constants.SECRET_ID, code)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<AccessTokenModel>() {
#Override
public void call(AccessTokenModel accessTokenModel) {
Log.e("WX", "accessToken:" + accessTokenModel.accessToken);
}
});
}
}
but I got an error:
java.lang.IllegalArgumentException: Unable to create call adapter for
rx.Observable
I think it's the way i transform the url wrong.But I don't know how to fix it.
i think you should include adapter-rxjava lib to your gradle dependencies.
compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta1'
and then add call adapter factory to your retrofit builder
public WXRest() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(WXBaseUrl)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
mWXService = retrofit.create(WXService.class);
}

AbstractMethodError when using RxJavaCallAdapterFactory on Retrofit 2

I get this error:
FATAL EXCEPTION: main
E/AndroidRuntime: java.lang.AbstractMethodError: abstract method not implemented
at retrofit.RxJavaCallAdapterFactory.get(RxJavaCallAdapterFactory.java)
at retrofit.Retrofit.nextCallAdapter(Retrofit.java:189)
at retrofit.Retrofit.callAdapter(Retrofit.java:175)
at retrofit.MethodHandler.createCallAdapter(MethodHandler.java:45)
at retrofit.MethodHandler.create(MethodHandler.java:26)
at retrofit.Retrofit.loadMethodHandler(Retrofit.java:151)
at retrofit.Retrofit$1.invoke(Retrofit.java:132)
at $Proxy0.getPosts(Native Method)
when trying to use RxJavaCallAdapterFactory on retrofit. I'm using com.squareup.retrofit:retrofit:2.0.0-beta1 and com.squareup.retrofit:adapter-rxjava:2.0.0-beta1.
Here's how I created the api interface:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(FORUM_SERVER_URL)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
mForumApi = retrofit.create(ForumApi.class);
The FORUM_SERVER_URL is
private static final String FORUM_SERVER_URL = "http://jsonplaceholder.typicode.com";
my interface method is:
#GET("/posts")
public Observable<List<Post>> getPosts();
I call it via:
mForum.getApi()
.getPosts()
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<List<Post>>() {
#Override
public void onCompleted() {}
#Override
public void onError(Throwable e) {}
#Override
public void onNext(List<Post> posts) {
mView.displayPosts(posts);
}
});
}
getApi returns mForumApi
getPosts is where the error happens, it's the API call
For me it turned out that I was using different beta versions of the components
Changing (notice beta1):
compile 'com.squareup.retrofit:converter-simplexml:2.0.0-beta2'
compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta1'
to (now beta2)
compile 'com.squareup.retrofit:converter-simplexml:2.0.0-beta2'
compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta2'
made it work for me.
Stupid error but yeah...

Categories

Resources