Reterofit not returning Response Android - android

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();

Related

Retrofit 2 is not receiving response inside AsyncTask every 1, 3, 5... time

I am using Retrofit to receive response, but every 1st, 3rd, 5th... time there is no response coming after Button click (I checked by Postman or Webbrowser in different networks - there is always response). In debug mode every second time is not even entering to onResponse() or onFailure() methods:
This is my MainActivity.class
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...//some not important code
Button syncButton = findViewById(R.id.syncBtn);
syncButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AsyncTaskRunner asyncTaskRunner = new AsyncTaskRunner();
asyncTaskRunner.execute();
}
});
}
This is my AsyncTaskRunner.class:
private class AsyncTaskRunner extends AsyncTask<String, String, List<GetCheapestResponseType>> {
#Override
protected List<GetCheapestResponseType> doInBackground(String... strings) {
...//some not important code
MutableLiveData<List<GetCheapestResponseType>> getCheapestResponseTypeMutableListData = new MutableLiveData<>();
List<GetCheapestResponseType> getCheapestResponseTypeList = new LinkedList<>();
...//some not important code
MutableLiveData<GetCheapestResponseType> getCheapestResponseTypeMutableLiveData = getCheapestOneWay(...);
getCheapestResponseTypeList.add(getCheapestResponseTypeMutableLiveData.getValue());
...//some not important code
return getCheapestResponseTypeList.add(getCheapestResponseTypeMutableLiveData.getValue());
}
}
This is my getCheapestOneWay(...); method with Retrofit:
public MutableLiveData<GetCheapestResponseType> getCheapestOneWay(...) {
...//some not important code
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(urlGetCheapest)
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
Controller controller = retrofit.create(Controller.class);
Call<GetCheapestResponseType> callAsync = controller.getCheapest(...);
callAsync.enqueue(new Callback<GetCheapestResponseType>() {
#Override
public void onResponse(Call<GetCheapestResponseType> call, Response<GetCheapestResponseType> response) {
if (response.isSuccessful()) {
GetCheapestResponseType apiResponse = response.body();
mutableLiveData.postValue(apiResponse);
} else {
...//some not important code
}
}
#Override
public void onFailure(Call<GetCheapestResponseType> call, Throwable throwable) {
...//some not important code
}
});
return mutableLiveData;
}

Android - How to use viewmodel for handling http call in OnCreate which doesn't get called on screen rotation?

. 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) {
}
});
}
}

call.enqueue dont get called in Retrofit Android with Mvvm architecture

I am implementing get request with Retrofit in Mvvm architecture, but call.enqueue is not getting executed. When i try it without mvvm architecture in simple activity it works fine.
Github:
https://github.com/nikolabozicbg/Retrofit
I tried to log onresponse and onfailure but nothing gets logged
Here is my Fragment code:
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
listItemViewModel = ViewModelProviders.of(this, viewModelFactory)
.get(ListGamesViewModel.class);
listItemViewModel.getListItems().observe(this, new Observer<List<ListGames>>() {
#Override
public void onChanged(#Nullable List<ListGames> listItems) {
}
});
}
View model code:
public class ListGamesViewModel extends ViewModel {
private RetrofitRpository repository;
public ListGamesViewModel(RetrofitRpository repository) {
this.repository = repository;
}
public LiveData<List<ListGames>> getListItems() {
System.out.println("iz live model");
return (LiveData<List<ListGames>>) repository.getListOfData();
}
}
Repository code:
public class RetrofitRpository {
List<ListGames> listItemList;
public RetrofitRpository() {
}
public List<ListGames> getListOfData() {
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("http://mobilews.365scores.com/").addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
LisgGamesCLient client = retrofit.create(LisgGamesCLient.class);
Call<Example> call = client.reposForUser();
call.enqueue(new Callback<Example>() {
#Override
public void onResponse(Call<Example> call, Response<Example> response) {
System.out.println("onresponse");
}
#Override
public void onFailure(Call<Example> call, Throwable t) {
System.out.println("onfail");
}
});
return listItemList;
}
}
CLient code:
public interface LisgGamesCLient {
#GET("Data/Games/?lang=1&uc=6&tz=15&countries=1")
Call<Example> reposForUser();
}
Example class code:

Retrofit getting data from web throws null object reference

I'm trying to get data from web api but something is wrong and I can't figure it out.
My JSON looks like this
{
"partners":
[
"partner1",
"partner2",
"partner3",
... ,
"partner150"
]
}
I have Table partners (ActiveAndroid) in which I would like to save all partners from api.
#Table(name = "Partners")
public class Partners extends Model {
#Column(name = "Name")
String name;
public Partners() {}
public Partners(String name) {
this.name = name;
}
}
Here is my Pojo model class:
public class Partners extends ArrayList<String> {
#SerializedName("partners")
#Expose
public List<String> partners = new ArrayList<String>();
public List<String> getPartners() {
return partners;
}
public void setName(List<String> partners) {
this.partners = partners;
}
}
This is my interface
public interface APIService {
#GET("Partners")
Call<Partners> getPartners();
}
This is my APIHelper class
public class APIHelper {
public static final String PARTNERS_URL = "https://part-of-link.com/partners.json/";
public static APIService apiService;
public static APIService getApiService() {
if (apiService == null) {
Retrofit retrofit = new Retrofit.Builder().baseUrl(PARTNERS_URL)
.addConverterFactory(GsonConverterFactory.create()).build();
apiService = retrofit.create(APIService.class);
}
return apiService;
}
}
And this is Fragment where I have an Button on which I would like to implement onClick method to get data from API and save it into Partners table.
public class DownloadMain extends Fragment implements Callback<Partners> {
private Button dloadPartners;
private Call<Partners> callPartners;
public static APIService apiService;
public DownloadMain() {}
public DownloadMain newInstance() { return new DownloadMain(); }
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.download_main, container, false);
dloadPartners = (Button) view.findViewById(R.id.downloadPartners);
dloadPartners.setOnClickListener(btnListener);
callPartners = APIHelper.getApiService().getPartners();
callPartners.enqueue(this);
return view;
}
Button.OnClickListener btnListener = (new View.OnClickListener() {
#Override
public void onClick(View v) {
APIHelper helper = new APIHelper();
apiService = helper.getApiService();
Call<Partners> call = apiService.getPartners();
call.enqueue(new Callback<Partners>() {
#Override
public void onResponse(Call<Partners> call, Response<Partners> response) {
APIHelper helper = new APIHelper();
helper.getApiService();
Call<Partners> call = apiService.getPartners();
call.enqueue(new Callback<Partners>() {
#Override
public void onResponse(Call<Partners> call, Response<Partners> response) {
List<String> partners = response.body().getPartners();
Log.d(TAG, "Number of partners received: " + partners.size());
/*if (response.body() != null) {
ArrayList<String> partnersList;
partnersList = response.body();
Log.d("DOWNLOAD", String.valueOf(partnersList));
}*/
}
#Override
public void onFailure(Call<Partners> call, Throwable t) {
Toast.makeText(getActivity(), "FAIL!!!", Toast.LENGTH_SHORT).show();
}
});
}
});
#Override
public void onResponse(Call<Partners> call, Response<Partners> response) {
}
#Override
public void onFailure(Call<Partners> call, Throwable t) {
}
}
And here is my problem. Everything works and there is no errors but when I click on button nothing happens.
So I presume I've made some mistake but I can't figure it out (First time doing with retrofit).
What I want on button click is to get all partners from web and save it into my Partners table.
Question: Could somebody guide me and tell me what is wrong and help me to fix this?
EDIT:
Button.OnClickListener btnListener = (new View.OnClickListener() {
#Override
public void onClick(View v) {
APIHelper helper = new APIHelper();
apiService = helper.getApiService();
Call<ArrayList<String>> call = null;
call.enqueue(new Callback<ArrayList<String>>() {
#Override
public void onResponse(Call<ArrayList<String>> call, Response<ArrayList<String>> response) {
ArrayList<String> partners = response.body();
Log.d(TAG, "Number of partners received: " + partners.size());
}
#Override
public void onFailure(Call<ArrayList<String>> call, Throwable t) {
Toast.makeText(getActivity(), "FAIL!!!", Toast.LENGTH_SHORT).show();
}
});
}
});
Error logs:
Error:(68, 60) error: is not abstract and does not
override abstract method
onResponse(Call>,Response>) in
Callback
Error:(72, 53) error: cannot find symbol method body()
Error:(69, 17) error: method does not override or implement a method
from a supertype
Error:Execution failed for task ':app:compileDebugJavaWithJavac'.
Compilation failed; see the compiler error output for details.
your problem is here in the onClick()
helper.getApiService();
you did not assign the service into the variable
change it to this:
apiService = helper.getApiService();
EDIT:
based on new updates i think you dont need to use a POJO
just use the following in your Call
Call<ArrayList<String>>
and to get response just use response.body() without .partners() .
try to replace it everywhere in your code and check
Based on your JSON response, your POJO class should be:
public class Partners {
private ArrayList<String> partners = new ArrayList<>(0);
// Get; Set methods //
}
Try putting this in your APIHelper class to get more information about what you are sending
public static APIService apiService;
//this http loggin interceptor allows you debug requests and responses
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
// set your desired log level
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
// add your other interceptors …
// add logging as last interceptor
httpClient.addInterceptor(logging); // <-- this is the important line!
public static APIService getApiService() {
if (apiService == null) {
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
}
return apiService;
}
Maybe you are sending information in a wrong way...
And remember that in server side you must decode the information that receive (with json_decode).

Getting error while using Retrofit and Rxjava

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

Categories

Resources