I'm using Mockito to test my views but my tests are failing because of a method that is supposed to be called after a retrofit call is complete. How can I mock a view who's method is called by presenter after completion of a retrofit call? I'd like to verify that unBlockUI() below has been called. My tests show blockUI() is called but unblockUI() is not being called.
I get a fail message
Wanted but not invoked:
view.unBlockUI();
In my presenter I have the method
public void fetchResults(){
view.blockUI();
ResultsDataService resultsDataService = new ResultsDataService()
resultsDataService.getAllResults(new Callback<Catalog>() {
#Override
public void onResponse(Call<Catalog> call, Response<Catalog> response) {
view.unBlockUI();
}
#Override
public void onFailure(Call<Catalog> call, Throwable t) {
view.unBlockUI();
t.printStackTrace();
}
})
}
Results data service.
public class ResultsDataService {
private final RestApi restApi;
public CatalogDataService() {
//here I have a class that builds the REST Service
restApi = RestServiceBuilder.createService(RestApi.class);
}
public void getAllResults() {
Call<Catalog> call = restApi.getAllResults();
call.enqueue(callback);
}
}
my test method
#Test
public void shouldFetchAllResults_allOK() {
presenter.fetchResults();`
verify(view).blockUI();//This is called
verify(view).unBlockUI();//this is not called
}
I think one possible solution is to mock ResultsDataService to call the onResponse method of any callback every time getAllResults is called.
Unfortunately, the way you're creating your ResultsDataService inside fetchResults makes it really hard to do this. This is what we call tight coupling. You have a method that depends strictly on ResultsDataService with no chance to change it. Therefore you cannot control the presenter from the outside. As a rule of thumb, every time you see the new operator that's a sign of tight coupling.
Usually we use dependency injection to solve this. One way you can do it in your code is simply change the fetchResults method to receive the service as an argument:
public void fetchResults(#NonNull ResultsDataService service) {
// ...
}
It might not seem much, but now in the test you can pass in a configured mock and in your app you just pass in the real service.
Say now in your test you'd configure a mock like so:
ResultDataService service = mock(ResultDataService.class);
doAnswer(new Answer() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
Call call = (Call) invocation.getArgument(0);
call.onResponse(call, <some response here>);
return null;
}
}).when(service.getAllResults(any(Call.class)));
You can now use this to pass it to your presenter fetchResults.
What does the mock above do? It will call the onResponse method of the passed in argument. So basically it will call right away the onResponse callback when you call fetchResults. In your case this will in turn call unBlockUI.
Notice you can do something similar to test the onFailure. You should also make ResultsDataService an interface, so your presenter doesn't depend on concrete implementations, but just interfaces. This is much more flexible.
Hope this helps. Remember, this is one way of doing this and not the single way.
Related
I have a MVVM architecture in my Android app. In an activity, I invoke a method to try to create something from service/repository and return it. I am using RxJava.
Here is the flow:
I click something in view, it invokes method in the Activity.
Method in Activity invokes method in ViewModel.
Method in ViewModel invokes method in Interactor(/use-case).
Interactor has access to service and tries to create something from that service.
Here is the code for this:
Activity:
#Override
public void onCreateWalletClick(String password) {
addWalletViewModel.createWallet(password);
}
ViewModel:
public class AddWalletViewModel extends BaseViewModel {
private AddWalletInteractor addWalletInteractor;
private final MutableLiveData<Wallet> newWallet = new MutableLiveData<Wallet>();
private final MutableLiveData<ErrorCarrier> newWalletError = new MutableLiveData<ErrorCarrier>();
public LiveData<Wallet> newWallet() {
return newWallet;
}
public AddWalletViewModel(AddWalletInteractor addWalletInteractor) {
this.addWalletInteractor = addWalletInteractor;
}
public Single<Wallet> createWallet(String password){
return addWalletInteractor.addWallet(password)
.subscribe(wallet -> newWallet.postValue(wallet), this::addErrorToLiveData);
}
private void addErrorToLiveData(Throwable throwable){
newWalletError.postValue(new ErrorCarrier());
}
}
Interactor:
public class AddWalletInteractor {
private final KeyStoreServiceInterface keyStoreServiceInterface;
public AddWalletInteractor(KeyStoreServiceInterface keyStoreServiceInterface) {
this.keyStoreServiceInterface = keyStoreServiceInterface;
}
public Single<Wallet> addWallet(String password){
return keyStoreServiceInterface.
createWalletAndReturnWallet(password);
}
}
Service:
#Override
public Single<Wallet[]> getAllWallets() {
return Single.fromCallable(()-> {
Accounts accounts = keyStore.getAccounts();
int amount = (int) accounts.size();
Wallet[] wallets = new Wallet[amount];
for (int i = 0; i<amount; i++){
org.ethereum.geth.Account gethAccount = accounts.get(i);
wallets[i] = new Wallet(gethAccount.getAddress().getHex().toLowerCase());
}
return wallets;
}).subscribeOn(Schedulers.io());
}
Problem is I can not manage to get this to work by tweaking the code. Right now it forces me to cast to (Single) in the return of the createWallet() method in the viewmodel. When running the app, it crashes in that method with:
java.lang.ClassCastException:
io.reactivex.internal.observers.ConsumerSingleObserver cannot be cast
to io.reactivex.Single
at addwallet.AddWalletViewModel.createWallet(AddWalletViewModel.java:31)
Please keep in mind I am new to RxJava, I am still trying to figure it out. Any suggestions here?
The cast performed in the createWallet method will always fail.
Solution 1
The simplest way to fix the crash is to change the return type of that method to io.reactivex.disposables.Disposable, assuming you're using RxJava 2. If you're using RxJava 1, then have it return rx.Subscription. The code you presented that calls the createWallet method doesn't seem to use the returned value so it shouldn't make a difference.
Solution 2
If you really do need the return type to be Single and you want to keep the same behavior, then an alternate solution would be to change the createWallet method as follows:
public Single<Wallet> createWallet(String password) {
return addWalletInteractor.addWallet(password)
.doOnSuccess(wallet -> newWallet.postValue(wallet))
.doOnError(this::addErrorToLiveData);
}
The method now returns a new Single that does whatever the Single returned from addWallet does and additionally invokes the appropriate lambda function when a value is successfully emitted or an error occurs. You would also need to modify the call site for the method as follows:
#Override
public void onCreateWalletClick(String password) {
addWalletViewModel.createWallet(password).subscribe();
}
That subscribe call is needed to have the Single start emitting values. It takes no parameters because you already do all of the interesting work in the createWallet method itself. Both snippets were written with RxJava 2 in mind, but I believe they will also work in RxJava 1 as is.
If you haven't already done so, you should check out the official Rx website as it provides a ton of information on how reactive streams work and how to use them.
Since you're new to RxJava and the documentation is so vast, here's a brief overview of the subscription concept and how it applies to your situation.
RxJava and other stream-based libraries like it have two main components: producers and consumers. Producers supply values and consumers do something with those supplied values.
Single is a kind of producer that only produces one value before terminating. In your case, it produces a reference to the newly created wallet. In order to do something with that reference, it needs to be consumed. That's what the subscribe method on the Single class does. When the Single returned by the addWallet method produces a value, the lambda passed to the subscribe method is invoked and the wallet parameter in that lambda is set to the produced value.
The return type of the subscribe method is NOT itself a Single. When a consumer and a producer are coupled together by the subscribe method, it forms a connection which is represented by the Disposable class. An instance of that class has methods to cancel the connection before the producer is done producing values or to check if the connection has been cancelled. It is this connection object that is returned by the subscribe method.
Note that until this connection is made via one of the subscribe overloads, the producer will not start producing items. I.e., a Single that is never subscribed to will never do anything. It's analogous to a Runnable whose run method is never called.
I have this class with these structure and i need test the behaviour of OnRequestListOfLunchsFinished interface
#Override
public void getListOfLunchs(final OnRequestListOfLunchsFinished callback) {
zip().onErrorResumeNext(new Function<Throwable, ObservableSource<? extends LunchServiceResponse>>() {
#Override
public ObservableSource<? extends LunchServiceResponse> apply(#NonNull Throwable throwable) throws Exception {
callback.onError(new RuntimeException(throwable));
callback.onEnd();
return Observable.empty();
}
}).subscribe(new Consumer<LunchServiceResponse>() {
#Override
public void accept(LunchServiceResponse response) throws Exception {
List<Lunch> result = new ArrayList<>();
List<IngredientResponseVO> ingredients = response.getIngredients();
Map<Integer, Ingredient> hash = new HashMap<Integer, Ingredient>();
for (IngredientResponseVO vo : ingredients)
hash.put(vo.id, new Ingredient(vo.id, vo.name, new BigDecimal(vo.price.toString()), vo.image));
for(InfoLunchResponseVO vo: response.getLunch()){
Lunch lunch = new Lunch();
lunch.setId(vo.id);
lunch.setImage(vo.image);
lunch.setName(vo.name);
for(Integer id : vo.ingredients){
Ingredient ingredient = hash.get(id);
lunch.addIngredient(ingredient);
}
result.add(lunch);
}
callback.onSuccess(result);
callback.onEnd();
}
});
callback.onStart();
}
private Observable<LunchServiceResponse> zip(){
return Observable.zip(getRequestOfListOfLunchs(), getRequestOfListOfIngredients(), new BiFunction<List<InfoLunchResponseVO>, List<IngredientResponseVO>, LunchServiceResponse>() {
#Override
public LunchServiceResponse apply(#NonNull List<InfoLunchResponseVO> infoLunchResponseVOs, #NonNull List<IngredientResponseVO> ingredientResponseVOs) throws Exception {
return new LunchServiceResponse(infoLunchResponseVOs, ingredientResponseVOs);
}
});
}
i have this test method
#Test
public void teste(){
List<IngredientResponseVO> ingredients = Collections.emptyList();
List<InfoLunchResponseVO> lunchs = Collections.emptyList();
when(mockApi.getListOfIngredients()).thenReturn(Observable.just(ingredients));
when(mockApi.getLunchs()).thenReturn(Observable.just(lunchs));
mockImplementation.getListOfLunchs(callback);
InOrder order = inOrder(callback);
order.verify(callback).onStart();
order.verify(callback).onSuccess(anyList());
order.verify(callback).onEnd();
order.verifyNoMoreInteractions();
}
but i am receiving the exception:
org.mockito.exceptions.verification.VerificationInOrderFailure:
Verification in order failure
Wanted but not invoked:
callback.onSuccess(<any>);
if i do this:
callback.onStart();
callback.onSuccess(Collections.<Lunch>emptyList());
callback.onEnd();
InOrder order = inOrder(callback);
order.verify(callback).onStart();
order.verify(callback).onSuccess(anyList());
order.verify(callback).onEnd();
order.verifyNoMoreInteractions();
this works.
how verify only calls of my mock callback?
You just must not use the InOrder object.
mockImplementation.getListOfLunchs(callback);
Mockito.verify(callback).onStart();
Mockito.verify(callback).onSuccess(anyList());
Mockito.verify(callback).onEnd();
Mockito.verifyNoMoreInteractions();
AFAICS the issue is not with the test but with your reading of the test results (jumping ahead: I believe it found a bug in your code).
Probably in the real code your getListOfIngredients and getLunchs do some network requests i.e. they are asynchronous to the call to getListOfLunchs and (zip inside of it). Thus in the real code onStart is called immediately on the caller thread while onSucess and onEnd are called later. However in your test you mock those API calls with very synchronous Observable.just and thus the order of execution is different: first onSuccess is called, then onEnd and finally onStart (you can easily validate this if you substitute your mocked callback with a custom one that just logs method name in every call).
You probably expeceted that since you use verifyNoMoreInteractions you would get a error about wrong order of onStart. Unfortunatelly this is not how it works. Since your order verifications are specified earlier, they are checked earlier. And in those checks there is yet no restriction of "no more". So what happens is roughly following:
onSucess is called. InOrder check ignores it because there was no onStart yet
onEnd is called. InOrder check ignores it because there was no onStart yet
onStart is called. This matches what InOrder expects and now it waits for onSucess. However this (second) onSuccess never comes and this is exactly what the error says.
So what to do? First of all I'd like to say that IMHO this failed test did find a very real bug in your code. Assume that at some point in the future someone added a caching layer to your API so sometimes getListOfIngredients and getLunchs return immediately with a synchronous result. In such case your code breaks contract of the OnRequestListOfLunchsFinished that onStart should be called first. So the proper way is to fix your code. An obvious but possible wrong way is to move the line
callback.onStart();
to the start of the method. (Why it is possibly wrong? Can your zip throw an Exception? If it does, what happens to the state of the callback?). Another way is to do the same as you do with onEnd i.e. copy it inside both success and error handling code in proper order.
I am new in Android and Retrofit and I am facing one problem.
I want to have my lets say "ServerCommunication" class (singelton) where all Retrofit magic is done and it will have public methods where REST calls are done.
I want to use this "ServerCommunication" instance in my activities to call Rest service, but thats it. Application logic should be done in activity. So this way some activity Login calls method Login(POJORequest) in "ServerCommunication) where actual REST call via Retrofit framework is done and some POJOResponse is returned. So Activity doesn't care about REST communication while ServerCommunication doesn't care about what logic that should be applied to response from REST service since.
With retrofit 2 I do not understand how I can block Activity to wait for response from retrofit and how it can be returned. Well, I might think I can use some callback methods in activity so those methods can be called from ServerCommunication" in OnPostExecute() to apply some logic based on data from response. It's just I think it should be simpler approach.
Well, to clarify all this mess above imagine simple case: You have data in you main activity, you pass this data to your communication class where REST call is done and response is received. This response must be validated in order to continue. And you want this validation to be done in main activity and NOT in communication class.
What is pattern to do that in Android with Retrofit2 ?
Thank you in advance
What I normally do:
Create your Interface (where you have all your REST methods - GET & POST etc)
Create a class that does the actual calls with corresponding methods (refer to the interface REST methods). I would call it something like ServiceAPIImplementor. This is where you actually create your Retrofit adapter.
In your activity, create an instance of your implementor class and call the methods and pass the expected arguments.
After calling the methods, you should probably show a progress dialog to let the user know that something is going on.
When the onResponse or onFailure method is called, use an Event pattern (EventBus library?) to notify the activity that the network operation has been completed. Once the activity has received the notification, it should then dismiss the progress dialog and update the UI accordingly - with the newly received data or completed operation (expected outcome).
I hope this helps you get closer to what you are trying to achieve!
Service interface (IPhotoService):
#GET("/photos/kudos")
Call<String> fetchKudos(#Header("Authorization") String authorization,
#Query("offset") int offset, #Query("mt") boolean mt);
Service impl (PhotoService):
private GoApiProvider<IPhotoService> mGoProvider = new GoApiProvider<>();
public Promiser<List<Photo>, HttpError> fetchKudos() {
return new Promiser<>((resolve, reject) ->
mGoProvider.getService(IPhotoService.class).fetchKudos(mSession.getToken(),
mOffsetKudos, true).enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
if (response.isSuccessful()) {
PhotoParser JSON = new PhotoParser();
try {
mOffsetKudos = mOffsetKudos + 20;
resolve.run(JSON.photosFromJson(response.body()));
} catch (JSONException e) {
Log.e("fetchKudos", e.toString());
}
} else {
reject.run(new HttpError(response.code(), response.message()));
}
}
#Override
public void onFailure(Call<String> call, Throwable t) {
reject.run(new HttpError(YPErrorType.Undefined.getType(), t.getMessage()));
}
})
);
}
Activity or Fragment :
private void loadPhoto() {
new PhotoService().fetchKudos()
.success(this::resultSucceeded)
.error(this::resultError);
}
private void resultSucceeded(List<Photo> photos) {
mPhotoAdapter.setItems(photos);
}
private void resultError(HttpError httpError) {
httpErrorToast(httpError);
}
If you want to use Promizer: Click here
I have a function that I want to test which runs in an okHttp callback. I'm trying to test it using Robolectrics but the callback is never executed. I presume that is because the test moves on after request without waiting for okHttp to return. So far I've tried:
ShadowLooper.pauseMainLooper();
Robolectric.flushBackgroundScheduler();
ShadowLooper.unPauseMainLooper();
but that didn't work. Any suggestions?
EDIT:
Here's an example of my code:
ApiClient.sendSomeDataToServer(data, callback);
Where ApiClient is a helper class containing okHttp client. sendSomeDataToServer API call looks something like this:
public static void sendSomeDataToServer(MyObject data, Callback callback){
final Request request = new Request.Builder()
.url(API_SOME_URL)
.post(RequestBody.create(JSON, myObject.getAsJson().toString()))
.build();
sHttpClient.newCall(request).enqueue(callback);
}
Where sHttpClient is an initialised OkHttpClient.
I can test the execution of above by forcing Thread.sleep(5000) inside my test code and providing custom callback. The code I'm trying to test is inside the callback. Any suggestions how I can test that? I really don't want to change the main code to fit the test framework - should be the other way round.
Lets assume you have next code. Interface:
#GET("/user/{id}/photo")
void listUsers(#Path("id") int id, Callback<Photo> cb);
Implementation:
public void fetchData() {
RestAdapter restAdapter = new RestAdapter.Builder()
.setServer("baseURL")
.build();
ClientInterface service = restAdapter.create(ClientInterface.class);
Callback<Photo> callback = new Callback<Photo>() {
#Override
public void success(Photo o, Response response) {
}
#Override
public void failure(RetrofitError retrofitError) {
}
};
service.listUsers(435, callback);
}
First of all you need to change service instantiation to service injection (as parameter or field). I will do it as parameter:
public void fetchData(ClientInterface clients) {
}
After this text is quite trivial:
#Test
public void checkThatServiceSuccessIsProcessed() {
ClientInterface mockedClients = mock(ClientInterface.class);
activity.fetchData(mockedClients);
// get callback
ArgumentCaptor<Callback<Photo>> captor = (ArgumentCaptor<Callback<Photo>>)ArgumentCaptor.forClass(Callback.class);
verify(mockedInterface).listUsers(anything(), captor.capture());
Callback<Photo> passedCallback = captor.value();
// run callback
callback.success(...);
// check your conditions
}
The used library for mocking and verifying is Mockito.
There will be one warning with captor instantiation because of generics but it fixable if you will use #Captor annotation instead of creating captor by hands.
The parameter injection is not perfect, especially for case of activities. This was used to simplify example. Consider for proper injection with library or without. I would encourage you to try Dagger for injections
You can use ArgumentCaptor (Mockito's class).
Reference:
http://www.mdswanson.com/blog/2013/12/16/reliable-android-http-testing-with-retrofit-and-mockito.html
I'm switching to Retrofit and trying to understand proper architecture for using it with async callbacks.
For example I have an interface:
interface RESTService{
#GET("/api/getusername")
void getUserName(#Query("user_id") String userId,
Callback<Response> callback);
}
And I run this from main activity:
RestAdapter restAdapter = new RestAdapter.Builder()
.setServer("WEBSITE_URL")
.build();
RESTService api = restAdapter.create(RESTService.class);
api.getUserName(userId, new Callback<Response> {...});
Then user rotates the device and I have newly created activity... What was happen here? How can I get response to the new activity (I assume that api call in background will execute longer than first activity life). Maybe I must use static instance of callback or what? Please show me the right way...
Use otto.
There are a lot of samples to mix otto and retrofit, for example https://github.com/pat-dalberg/ImageNom/blob/master/src/com/dalberg/android/imagenom/async/FlickrClient.java
Or read this post http://www.mdswanson.com/blog/2014/04/07/durable-android-rest-clients.html
It answers on almost all questions
For potential long running server calls i use an AsyncTaskLoader. For me, the main advantage of Loaders are the activity-lifecycle handling. onLoadFinished is only called if your activity is visible to the user. Loaders are also shared between activity/fragment and orientation changes.
So i created an ApiLoader which uses retrofits synchronous calls in loadInBackground.
abstract public class ApiLoader<Type> extends AsyncTaskLoader<ApiResponse<Type>> {
protected ApiService service;
protected ApiResponse<Type> response;
public ApiLoader(Context context) {
super(context);
Vibes app = (Vibes) context.getApplicationContext();
service = app.getApiService();
}
#Override
public ApiResponse<Type> loadInBackground() {
ApiResponse<Type> localResponse = new ApiResponse<Type>();
try {
localResponse.setResult(callServerInBackground(service));
} catch(Exception e) {
localResponse.setError(e);
}
response = localResponse;
return response;
}
#Override
protected void onStartLoading() {
super.onStartLoading();
if(response != null) {
deliverResult(response);
}
if(takeContentChanged() || response == null) {
forceLoad();
}
}
#Override
protected void onReset() {
super.onReset();
response = null;
}
abstract protected Type callServerInBackground(SecondLevelApiService api) throws Exception;
}
In your activity you init this loader like this:
getSupportLoaderManager().initLoader(1, null, new LoaderManager.LoaderCallbacks<ApiResponse<DAO>>() {
#Override
public Loader<ApiResponse<DAO>> onCreateLoader(int id, Bundle args) {
spbProgress.setVisibility(View.VISIBLE);
return new ApiLoader<DAO>(getApplicationContext()) {
#Override
protected DAO callServerInBackground(ApiService api) throws Exception {
return api.requestDAO();
}
};
}
#Override
public void onLoadFinished(Loader<ApiResponse<DAO>> loader, ApiResponse<DAO> data) {
if (!data.hasError()) {
DAO dao = data.getResult();
//handle data
} else {
Exception error = data.getError();
//handle error
}
}
#Override
public void onLoaderReset(Loader<ApiResponse<DAO>> loader) {}
});
If you want to request data multiple times use restartLoader instead of initLoader.
I've been using a kind of MVP (ModelViewPresenter) implementation on my Android apps. For the Retrofit request I made the Activity calls it's respective Presenter, which in turn makes the Retrofit Request and as a parameter I send a Callback with a custom Listener attached to it (implemented by the presenter). When the Callback reach onSuccess or onFailure methods I call the Listener's respective methods, which calls the Presenter and then the Activity methods :P
Now in case the screen is turned, when my Activity is re-created it attaches itself to the Presenter. This is made using a custom implementation of Android's Application, where it keeps the presenters' instance, and using a map for recovering the correct presenter according to the Activity's class.
I don't know if it's the best way, perhaps #pareshgoel answer is better, but it has been working for me.
Examples:
public abstract interface RequestListener<T> {
void onSuccess(T response);
void onFailure(RetrofitError error);
}
...
public class RequestCallback<T> implements Callback<T> {
protected RequestListener<T> listener;
public RequestCallback(RequestListener<T> listener){
this.listener = listener;
}
#Override
public void failure(RetrofitError arg0){
this.listener.onFailure(arg0);
}
#Override
public void success(T arg0, Response arg1){
this.listener.onSuccess(arg0);
}
}
Implement the listener somewhere on the presenter, and on the overrode methods call a presenter's method that will make the call to the Activity. And call wherever you want on the presenter to init everything :P
Request rsqt = restAdapter.create(Request.class);
rsqt.get(new RequestCallback<YourExpectedObject>(listener));
Firstly, your activity leaks here because this line:
api.getUserName(userId, new Callback {...})
creates an anonymous Callback class that holds a strong reference to you MainActivity. When the device is rotated before the Callback is called, then the MainActivity will not be garbage collected. Depending on what you do in the Callback.call(), your app may yield undefined behaviour.
The general idea to handle such scenarios is:
Never create a non-static inner class (or an anonymous class as mentioned in the problem).
Instead create a static class that holds a WeakReference<> to the Activity/Fragment.
The above just prevents Leaks. It still does not help you get the Retrofit call back to your Activity.
Now, to get the results back to your component (Activity in your case) even after configuration change, you may want to use a headless retained fragment attached to your Activity, which makes the call to Retrofit. Read more here about Retained fragment - http://developer.android.com/reference/android/app/Fragment.html#setRetainInstance(boolean)
The general idea is that the Fragment automatically attaches itself to the Activity on configuration change.
I highly recommend you watch this video given at Google I/O.
It talks about how to create REST requests by delegating them to a service (which is almost never killed). When the request is completed it is immediately stored into Android's built-in database so the data is immediately available when your Activity is ready.
With this approach, you never have to worry about the lifecycle of the activity and your requests are handled in a much more decoupled way.
The video doesn't specifically talk about retrofit, but you can easily adapt retrofit for this paradigm.
Use Robospice
All components in your app which require data, register with the spice service. The service takes care of sending your request to the server (via retrofit if you want). When the response comes back, all components which registered get notified. If there is one of them not available any more (like an activity which got kicked because of rotation), it's just not notified.
Benefit: One single request which does not get lost, no matter whether you rotate your device, open new dialogs/fragments etc...
Using Retrofit2 to handle orientation change. I was asked this in a job interview and was rejected for not knowing it at the time but here it is now.
public class TestActivity extends AppCompatActivity {
Call<Object> mCall;
#Override
public void onDestroy() {
super.onDestroy();
if (mCall != null) {
if (mCall.isExecuted()) {
//An attempt will be made to cancel in-flight calls, and
// if the call has not yet been executed it never will be.
mCall.cancel();
}
}
}
}