I am trying to implement RxJava and Retrofit2. But I am getting this error java.lang.IllegalArgumentException: Unable to create call adapter for rx.Observable
Here is my code :-
MainActivity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button bFetch = (Button) findViewById(R.id.button_fetch);
assert bFetch != null;
bFetch.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
GithubService service;
final Retrofit retrofit = new Retrofit.Builder()
.baseUrl(GithubService.SERVICE_ENDPOINT)
.addConverterFactory(GsonConverterFactory.create())
.build();
service = retrofit.create(GithubService.class);
Observable<Github> observable = service.getUser("writingminds");
observable.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Github>() {
#Override
public final void onCompleted() {
// do nothing
}
#Override
public final void onError(Throwable e) {
Log.e("GithubDemo", e.getMessage());
}
#Override
public final void onNext(Github response) {
Log.e("---%s", response.getBlog());
Log.e("--%s", response.getLogin());
}
});
}
});
}
}
And here is my Interface GithubService
public interface GithubService {
String SERVICE_ENDPOINT = "https://api.github.com";
#GET("/users/{login}")
Observable<Github> getUser(#Path("login") String login);
}
Here is my model :
public class Github {
private String login;
private String blog;
private int public_repos;
public String getLogin() {
return login;
}
public String getBlog() {
return blog;
}
public int getPublicRepos() {
return public_repos;
}
}
Thank you in advance
you need to tell Retrofit, you want to use RxJava. You can do it using
addCallAdapterFactory(RxJavaCallAdapterFactory.create())
E.g
final Retrofit retrofit = new Retrofit.Builder()
.baseUrl(GithubService.SERVICE_ENDPOINT)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
you will have to add
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
to your build.gradle dependency list, if you didn't it already
Related
I was testing the API in the Retrofit for first time, I was putting the code that they were showing but I don't know why my code doesn't work
it just shows that I am receiving the null value;
I was learning to implement the Retrofit library in my android app . so i was following some tutorial and i was following the code but don't know why i am getting this error
i tried to solve the error by changing the url but the response is the same it shows the null.
Please help me out
public class Todo {
private int userId;
private int id;
private String todo;
private boolean completed;
public int getUserId() {
return userId;
}
public int getId() {
return id;
}
public String getTitle() {
return todo;
}
public boolean isCompleted() {
return completed;
}
}
public interface ApiInterface {
#GET("/todo/{id}")
Call<Todo> getTodo(#Path("id") int id);
}
public class ApiClient {
private static final String BASE_URL ="https://dummyjson.com";
private static Retrofit retrofit= null;
public static Retrofit getclient(){
if(retrofit == null){
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
public class MainActivity extends AppCompatActivity {
TextView hello;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
hello= findViewById(R.id.textview);
ApiInterface apiInterface = ApiClient.getclient().create(ApiInterface.class);
Call<Todo> call =apiInterface.getTodo(1);
call.enqueue(new Callback<Todo>() {
#Override
public void onResponse(Call<Todo> call, Response<Todo> response) {
Log.e("info","onResponse"+response.body());
#Override
public void onFailure(Call<Todo> call, Throwable t) {
Log.e("info","onFailure" + t.getLocalizedMessage());
}
});
}
}
You are missing the plural 's' in todo. Change your path to #GET("/todos/{id}")
. Get stuck with a basic scenario of loading the data in oncreate of an activity. So I am trying to load the data as soon as i open my activity but when i change the screen orientation it gets called again.
below is my rest client for retrofit
public class MyRestApiClient {
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).connectTimeout(30,TimeUnit.SECONDS).readTimeout(30,TimeUnit.SECONDS).build();
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
retrofit = new Retrofit.Builder()
.baseUrl("http://localhost:8080/rest/")
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(client)
.build();
return retrofit;
}
}
below is my resturl interface for loading the data
public interface MyRestUrlInterface {
#GET("user/{user_id}")
Call<Object> getData(#Path("user_id") String user_id);
}
below is my viewmodel class:
public class MyViewModelObserver extends ViewModel {
private MutableLiveData<Object> httpCallBackObserver;
public MutableLiveData<Object> getHttpCallBackObserver() {
if (httpCallBackObserver == null) {
httpCallBackObserver = new MutableLiveData<Object>();
}
return httpCallBackObserver;
}
}
below is my Activity code :
public class MyActivity extends AppCompatActivity {
private static final String TAG = "MyActivity" ;
MyRestUrlInterface restUrlInterface;
public MyViewModelObserver myViewModelObserver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
restUrlInterface = MyRestApiClient.getClient().create(MyRestUrlInterface.class);
myViewModelObserver = ViewModelProviders.of(this).get(MyViewModelObserver.class);
myViewModelObserver.getHttpCallBackObserver().observe(this, getData());
//load data via http
Call<Object> call = restUrlInterface.getData("123");
call.enqueue(new Callback<Object>() {
#Override
public void onResponse(Call<Object> call, Response<Object> response) {
myViewModelObserver.getHttpCallBackObserver().setValue(response.body());
}
#Override
public void onFailure(Call<Object> call, Throwable t) {
}
});
}
private Observer<Object> getData(){
return new Observer<Object>() {
#Override
public void onChanged(#Nullable final Object responseString) {
Log.d(TAG,"***** Loaded Data --- "+responseString);
}
};
}
}
How to use view model so that it wont make http call again in screen orientation change
suggested answer:
public class MyViewModelObserver extends ViewModel {
private MutableLiveData<Object> httpCallBackObserver;
public MutableLiveData<Object> getHttpCallBackObserver() {
if (httpCallBackObserver == null) {
httpCallBackObserver = new MutableLiveData<Object>();
loadData();
}
return httpCallBackObserver;
}
private void loadData(){
Call<Object> call = restUrlInterface.getData("123");
call.enqueue(new Callback<Object>() {
#Override
public void onResponse(Call<Object> call, Response<Object> response) {
myViewModelObserver.getHttpCallBackObserver().setValue(response.body());
}
#Override
public void onFailure(Call<Object> call, Throwable t) {
}
});
}
}
I am using retrofit2 with rxjava2.
I have used mostly the latest library in my gradle and I have tried many methods for creating adapter .
I have also created some custom adapter but nothing seems to work with it
service :
public static Retrofit getClient() {
if (retrofit==null) {
retrofit = new Retrofit.Builder().baseUrl(AppConstants.BASE_URL)
.addConverterFactory(GsonConverterFactory.create()).
addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build();
}
return retrofit;
}
fragment code:
ApiInterface apiInterface
=ApiClient.getClient().create(ApiInterface.class);
apiInterface.getCategoryVideos(AppConstants.API_KEY)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Observer<Video>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(Video value) {
}
#Override
public void onError(Throwable e) {
}
#Override
public void onComplete() {
}
});
I have tried many adapters but no adapter is working . I am
the log output is :
Any suggestion or solution is appreciated .
I have also tried the solution in this link stackoverflow solution
Try to change create client
public class MyClient {
private static MyClient instance;
private ApiInterface apiInterface;
private MyClient() {
final Retrofit retrofit = new Retrofit.Builder().baseUrl(AppConstants.BASE_URL)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
gitHubService = retrofit.create(ApiInterface.class);
}
public static MyClient getInstance() {
if (instance == null) {
instance = new MyClient();
}
return instance;
}
}
and fragment code
private Subscription subscription;
...
subscription = MyClient.getInstance().getCategoryVideos(AppConstants.API_KEY)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Video>() {
#Override public void onCompleted() {
Log.d(TAG, "In onCompleted()");
}
#Override public void onError(Throwable e) {
e.printStackTrace();
Log.d(TAG, "In onError()");
}
#Override public void onNext(Video value) {
Log.d(TAG, "In onNext()");
}
});
How can I make the element in List<Contributor> of Observable<List<Contributor>> launch one by one like Observable<Contributor>.
"Contributor" is a custom class.
public class MainActivity extends AppCompatActivity {
private TextView mTv;
private interface GitHubService {
#GET("repos/{owner}/{repo}/contributors")
Observable<List<Contributor>> contributors(#Path("owner") String owner, #Path("repo") String repo);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTv= (TextView) findViewById(R.id.tv_content);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(new OkHttpClient())
.build();
GitHubService service=retrofit.create(GitHubService.class);
service.contributors("square","retrofit")
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<List<Contributor>>() {
#Override
public void call(List<Contributor> contributors) {
//TODO
}
});
}
}
That is my code. I want get the result like this finally :
subscribe(new Action1<Contributor>() {
#Override
public void call(Contributor contributor) {
//TODO
}
});
You can apply flatMap to Observable<List<...>> and create new observable from List:
Observable.just(Arrays.asList("A", "B", "C"))
.flatMap(new Func1<List<String>, Observable<String>>() {
#Override
public Observable<String> call(List<String> list) {
return Observable.from(list);
}
})
.subscribe(new Action1<String>() {
#Override
public void call(String x) {
System.out.println(x);
}
});
I am new to retrofit and trying to catch it up with a turorial at Reterofit Tutorial but Im unable to get any response from it. I have tried debuging the app with breakpoint inside the onResponse and onFailure but im ubale to hit these breakpoints. and dont know where getting wrong.
MainActivity:
public class MainActivity extends AppCompatActivity {
Toolbar toolbar;
ProgressDialog progressDialog=null;
public static final String Base_Url = "https://api.stackexchange.com";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.appBar);
//set support for toolbar
setSupportActionBar(toolbar);
ReteroFiller serverGet = new ReteroFiller();
serverGet.execute();
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu,menu);
return super.onPrepareOptionsMenu(menu);
}
private class ReteroFiller extends AsyncTask<String ,String,String> implements Callback<StackOverFlowQuestions>{
#Override
protected String doInBackground(String... strings) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.stackexchange.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
// prepare call in Retrofit 2.0
StackOverFlowAPI stackOverflowAPI = retrofit.create(StackOverFlowAPI.class);
Call<StackOverFlowQuestions> call = stackOverflowAPI.loadQuestions("android");
//asynchronous call
// call.enqueue();
// synchronous call would be with execute, in this case you
// would have to perform this outside the main thread
// call.execute()
// to cancel a running request
// call.cancel();
// calls can only be used once but you can easily clone them
//Call<StackOverflowQuestions> c = call.clone();
call.enqueue(this);
return null;
}
#Override
protected void onPostExecute(String result) {
// execution of result of Long time consuming operation
if(progressDialog!=null){
progressDialog.dismiss();
}
}
#Override
protected void onPreExecute() {
if(progressDialog==null){
progressDialog = ProgressDialog.show(MainActivity.this,
"ProgressDialog",
"Progressing");
}
}
#Override
protected void onProgressUpdate(String... text) {
}
#Override
public void onResponse(Call<StackOverFlowQuestions> call, Response<StackOverFlowQuestions> response) {
Log.i("RETERO TEST : ","Message: "+response.message()+" Body : "+response.body());
}
#Override
public void onFailure(Call<StackOverFlowQuestions> call, Throwable t) {
Toast.makeText(MainActivity.this, t.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
}
}
}
StackOverFlowQuestions Class
public class StackOverFlowQuestions {
List<Question> items;
}
Questions Model Class:
public class Question {
String title;
String link;
#Override
public String toString() {
return(title);
}
}
StackOverFlowAPI: Interface
public interface StackOverFlowAPI {
#GET("/2.2/questions?order=desc&sort=creation&site=stackoverflow")
Call<StackOverFlowQuestions> loadQuestions(
#Query("tagged") String tags
);
}
I just removed the asynctask it works fine , here is my Activity
public class MainActivity extends AppCompatActivity implements Callback<StackOverFlowQuestions> {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.stackexchange.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
StackOverFlowAPI stackOverflowAPI = retrofit.create(StackOverFlowAPI.class);
Call<StackOverFlowQuestions> call = stackOverflowAPI.loadQuestions("android");
call.enqueue(this);
}
#Override
public void onResponse(Call<StackOverFlowQuestions> call, Response<StackOverFlowQuestions> response) {
Log.d("RETERO TEST : ","Message: "+response.message()+" Body : "+response.body());
}
#Override
public void onFailure(Call<StackOverFlowQuestions> call, Throwable t) {
Toast.makeText(MainActivity.this, t.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
}
}
I used rest of your code, also I added the following gradle dependenies
//retrofit
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
AFAIK, you forgot to set client for your retrofit:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.stackexchange.com")
.addConverterFactory(GsonConverterFactory.create())
.client(new OkHttpClient.Builder()) // this is what you need!
.build();