Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrofit v2 Does Call.cancel() remove Callback?

I've read in the Retrofit v2 API Spec that calling the cancel() method on the Call class returned from your custom retrofit interface should set the Callback passed in to null.

cancel() is a no-op after the response has been received. In all other cases the method will set any callbacks to null (thus freeing strong references to the enclosing class if declared anonymously)

Going through the code I can't see that the Callback is explicitly set to null when cancel is called. I can see the callback being referenced in the OkHttpCall class (although not explicitly stored). Calling cancel will in turn call cancel on the RealCall class which takes care of the Http side of canceling, but does not concern itself with the stored callback in the AsyncCall class (which is put in the readyAsyncCalls and runningAsyncCalls queues in the Dispatcher class. It is unfamiliar code to me so I might be missing something.

Can someone confidently confirm that calling cancel() on my call object will remove reference to the Callback I've passed in so I don't leak memory?

Simplified code example:

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    final Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build();
    api = retrofit.create(Api.class);
}

@Override
public void onStart() {
    super.onStart();
    call = api.getPokedex();
    call.enqueue(new Callback<Pokedex>() {
        @Override
        public void onResponse(Call<Pokedex> call, Response<Pokedex> response) {
            populate(response.body());
        }

        @Override
        public void onFailure(Call<Pokedex> call, Throwable t) {
            error(t.getMessage());
        }
    });
}

@Override
public void onStop() {
    call.cancel();
    super.onStop();
}
like image 229
keith Avatar asked Feb 28 '16 17:02

keith


People also ask

What is callback in retrofit?

public interface Callback<T> Communicates responses from a server or offline requests. One and only one method will be invoked in response to a given request. Callback methods are executed using the Retrofit callback executor.


1 Answers

the reference to CallBack is not deleted, If you cancel a call according to Documentation Call#Cancel

  /**
   * Cancel this call. An attempt will be made to cancel in-flight calls, and if the call has not
   * yet been executed it never will be.
   */
  void cancel();

Anyway after Call is canceled, the CallBack is called namely the onFailure method.

public interface Callback<T> {
  /**
   * Invoked when a network exception occurred talking to the server or when an unexpected
   * exception occurred creating the request or processing the response.
   */
  void onFailure(Call<T> call, Throwable t);
}

The easiest way for you to test in your code if Call#isCanceled().

 @Override
        public void onFailure(Call<Pokedex> call, Throwable t) {
            Log.w(TAG, "Call is canceled: " + call.isCancelled());
            error(t.getMessage());
        }
like image 155
devzeze Avatar answered Sep 20 '22 08:09

devzeze