Retrofit and Activity Lifecycle - android

I want to make a REST Client with Android and I read about retrofit. When I do some requests with retrofit even if the activity is destroyed the callback is executed.
How can I stop receiving the response after the activity is being destroyed?
apiService.getDummieContent().enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});

You can assign the request to a variable and cancel it on activity destroy:
Call<ReponseBody> call = apiService.getDummieContent();
call.enqueue(...);
#Override
protected void onDestroy() {
super.onDestroy();
call.cancel();
}

You can declare global variable apiService
Call<ReponseBody> apiService;
and then call api method for instance here getDummieContent().Moreover you can manually check for the if call is cancelled in OnFaliure method. As in my case i was disabling swipeRefreshLayout which was getting null context on DestroyView because onFailure method was only called when view was destroyed, so with the help of this condition i always checked whether it is cancelled after on destroyed hence preventing exception.
apiService.getDummieContent().enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response)
{
// Do stuff here
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
t.printStackTrace();
if(call.isCanceled())
{
Log.e("isCanceled", " isCanceled");// check if it is cancelled on OnDestroy
}
}
});
and in on destory onDestroy
#Override
public void onDestroy() {
super.onDestroy();
call.cancel();
}

Related

OnResponse Callback Not trigger

in retrofit Client When Create data OnResponse Not Call
but Passing In the database
I cant intern in Another Activity.
public void saveUser(StudentName studentName){
Call<StudentName>call =ApiClient.getStudentName().sendStudentName(studentName);
call.enqueue(new Callback<StudentName>() {
#Override
public void onResponse(Call<StudentName> call, Response<StudentName> response) {
Intent intent = new Intent(StudentData.this,MainActivity.class);
startActivity(intent);
}
#Override
public void onFailure(Call<StudentName> call, Throwable t) {
}
});

How to return String from onResponse? Retrofit android studio

I've seen a few similar questions but they don't seem to answer my problem exactly. I've got a method that is supposed to return a string. I am using retrofit, but in onresponse, I can't return a string? Below is the code.
public String getInformation(String information, String username) {
String result;
Call<DefaultResponse> call = RetrofitClient.getInstance().getApi().getInformation(information,username);
call.enqueue(new Callback<DefaultResponse>() {
#Override
public void onResponse(Call<DefaultResponse> call, Response<DefaultResponse> response) {
result = response.body().getMsg();
}
#Override
public void onFailure(Call<DefaultResponse> call, Throwable t) {
}
});
return result;
}
The .enqueue method will take time to get the response, so your method will return before onResponse callback gets called.
Try using a callback approach for getInformation method and make it void:
public void getInformation(String information, String username, MyCallback callback) {
Call<DefaultResponse> call = RetrofitClient.getInstance().getApi().getInformation(information,username);
call.enqueue(new Callback<DefaultResponse>() {
#Override
public void onResponse(Call<DefaultResponse> call, Response<DefaultResponse> response) {
result = response.body().getMsg();
callback.success(result);
}
#Override
public void onFailure(Call<DefaultResponse> call, Throwable t) {
callback.failure(t)
}
});
}
With the MyCallback interface:
interface MyCallback {
void success(String result);
void failure(Throwable t);
}
Then you can call the method like this:
getInformation("Information", "Username", new MyCallback() {
#Override
public void success(String result) {
// Use result
}
#Override
public void failure(Throwable t) {
// Display error
}
});
You can use Result as output String wherever you want, as I used it in my adapter class in onBindViewHolder method, simply making object of the class from which string was sent and then calling the method (in which Interface was kept as parameter) & override success and failure method in adapter class and do whatever u want to do with this string......... Thanks a lot #y.allam & #Anonymous Cardinal :):)

how to check if Retrofit API call was successful in Android

here is my code:
by this method, I send some data to my API server
if data received successfully success variable will be true inside onResponse method
private boolean success=false;
public boolean commit(){
requestHandler.insertFields(tableName,values).enqueue(new Callback<DatabaseModel>() {
#Override
public void onResponse(Call<DatabaseModel> call,
Response<DatabaseModel> response) {
if (response.isSuccessful())
Log.i("debug8","result is:"+response.body().toString());
else
Log.e("debug8","error in server response:"+response.toString());
success=true;
}
#Override
public void onFailure(Call<DatabaseModel> call, Throwable t) {
Log.e("tempo",t.getMessage());
}
});
return success;//returns false before finishing the request
}
and in my activity i want to check the result like this:
Database db=new Database("cars");
db.put("field1","val1")
.put("field2","val2");
if(db.commit())
Toast.makeText(this, "data inserted successfully", Toast.LENGTH_SHORT).show();
else
Toast.makeText(this, "failed to insert new record", Toast.LENGTH_SHORT).show();
the problem is that always the commit method result is false because code returns false before retrofit enqueue method finishes its job
is it a good idea to make a custom listener or something like that to do this?
thanks in advance
Yes,you need to create listener for this because these calls happen asynchronously that's why it's returning always false.
You can create a interface like below.
public interface RetrofitResponseListener {
void onSuccess();
void onFailure();
}
And pass it as a argument in your method.
public void commit(final RetrofitResponseListener retrofitResponseListener) {
requestHandler.insertFields(tableName, values).enqueue(new Callback<DatabaseModel>() {
#Override
public void onResponse(Call<DatabaseModel> call,
Response<DatabaseModel> response) {
if (response.isSuccessful())
retrofitResponseListener.onSuccess();
else
retrofitResponseListener.onFailure();
}
#Override
public void onFailure(Call<DatabaseModel> call, Throwable t) {
retrofitResponseListener.onFailure();
}
});
}
And finally use this where you like:
private void setListener() {
commit(new RetrofitResponseListener() {
#Override
public void onSuccess() {
}
#Override
public void onFailure() {
}
});
}
Now do anything you want onSuccess or onFailure.
what happens there is the next: the request method is an async task, when you call it, it´ll start working on a second plane and your commit function continues with its sync flow which is return (the false value in this case).
you can try 2 things:
something like this,
public XX(whatever correspond) commit(){
return requestHandler.insertFields(tableName,values).enqueue(new Callback<DatabaseModel>() {
#Override
public void onResponse(Call<DatabaseModel> call,
Response<DatabaseModel> response) {
if (response.isSuccessful())
Log.i("debug8","result is:"+response.body().toString());
else
Log.e("debug8","error in server response:"+response.toString());
return true;
}
#Override
public void onFailure(Call<DatabaseModel> call, Throwable t) {
Log.e("tempo",t.getMessage()); return false;
}
});
}
and fix the if at the other side
or this way
public void commit(){
requestHandler.insertFields(tableName,values).enqueue(new Callback<DatabaseModel>() {
#Override
public void onResponse(Call<DatabaseModel> call,
Response<DatabaseModel> response) {
if (response.isSuccessful())
Log.i("debug8","result is:"+response.body().toString());
else
Log.e("debug8","error in server response:"+response.toString());
Toast.makeText(this, "data inserted successfully", Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(Call<DatabaseModel> call, Throwable t) {
Toast.makeText(this, "failed to insert new record", Toast.LENGTH_SHORT).show();
}
});}

how to start activity after call some requests by retrofit?

I want to start new activity after call and finish 7 difference requests in parallel using retrofit.
Where should I call startActivity() method?
here is my wrong trying.
new Thread(new Runnable() {
#Override
public void run() {
api.method1(args..).enqueue(new Callback<Response1>() {
#Override
public void onResponse(Call<Response1> call, Response<Response1> response) {
//do some things
}
#Override
public void onFailure(Call<Response1> call, Throwable t) {
t.printStackTrace();
}
});
..
..
..
api.method7(args..).enqueue(new Callback<Response7>() {
#Override
public void onResponse(Call<Response7> call, Response<Response7> response) {
//do some things
}
#Override
public void onFailure(Call<Response7> call, Throwable t) {
t.printStackTrace();
}
});
startActivity(new Intent(current.this,next.class));
}).start();
Use Rxjava with Retrofit and then you can do something like (assuming method1,method2 etc return Observable<Response1>, Observable<Response2> etc)
Observable.zip(api.method1, api.method2, ...)

Handle onResume in fragment

I have a fragment where I post request to server. This type of action should be in onResume() method, but I don't want to post request to server every time when I put app on background. Is exist any solution?
request which I want to post
FactoryAPI.getContacts().getContacts(user.getToken()).enqueue(new Callback<ContactsResponse>() {
#Override
public void onResponse(Call<ContactsResponse> call, Response<ContactsResponse> response) {
if(response.isSuccessful()) {
contactList = response.body().getContactsList();
sortList();
progressDialog.dismiss();
setRecyclerView();
}
}
#Override
public void onFailure(Call<ContactsResponse> call, Throwable t) {}
});
In your Fragment class, create a data member of type boolean like,
private boolean isResponseSend;
In your onResume() method,
#Override
public void onResume() {
super.onResume();
if(!isResponseSend)
{
isResponseSend = true;
//your code
FactoryAPI.getContacts().getContacts(user.getToken()).enqueue(new Callback<ContactsResponse>() {
#Override
public void onResponse(Call<ContactsResponse> call, Response<ContactsResponse> response) {
if(response.isSuccessful()) {
contactList = response.body().getContactsList();
sortList();
progressDialog.dismiss();
setRecyclerView();
}
}
#Override
public void onFailure(Call<ContactsResponse> call, Throwable t) {}
});
}
}
According to
https://developer.android.com/guide/components/fragments.html#Creating
you can post the request on
https://developer.android.com/reference/android/app/Fragment.html#onAttach(android.content.Context)
Use some variable like flag, and initialise it in the onCreate. and based on the flag, you can handle the request.

Categories

Resources