Android Getting Started tutorial | OkHttp + Retrofit method to cancel the request

Keywords: Android

In an interface, the user initiates a network request. For some reason, the user leaves the current interface before the network request is completed. It is better to cancel the network request. How do I find this network request and cancel it?

preface

In an interface, the user initiates a network request. For some reason, the user leaves the current interface before the network request is completed. It is better to cancel the network request. For OkHttp, it specifically calls the cancel method of Call.

How do I find this network request and cancel it?

The operation is roughly divided into three steps:

  • The first step is to mark the request when establishing the request;
  • The second step is to find the request according to the tag;
  • Finally, cancel the request.

tag in OkHttp

To cancel a request, you can use the cancel method in OkHttp.

The request object of OkHttp has a tag. The request can be marked according to the tag..

//Set tags for your requests when you build them:
    Request request = new Request.Builder().
    url(url).tag("requestKey").build();

    //When you want to cancel:
    //A) go through the queued calls and cancel if the tag matches:
    for (Call call : mHttpClient.dispatcher().queuedCalls()) {
        if (call.request().tag().equals("requestKey"))
            call.cancel();
    }

    //B) go through the running calls and cancel if the tag matches:
    for (Call call : mHttpClient.dispatcher().runningCalls()) {
        if (call.request().tag().equals("requestKey"))
            call.cancel();
    }

The interface to cancel the request is not explicitly provided in Retrofit. So how to find the target network request?

Retrofit adds a custom header

Add a custom header to each request related to the page (Activity, Fragment). Add an interceptor to OkHttpClient. Mark the survival status of the page. If the page is destroyed, cancel the corresponding request.

Take GitHub on Android project as an example

Add tag

Hold a concurrent HashMap to mark the page survival status.

private static ConcurrentHashMap<String, Boolean> actLiveMap = new ConcurrentHashMap<>(); // Mark whether the Activity is alive

    public static void markPageAlive(String actName) {
        actLiveMap.put(actName, true);
    }

    public static void markPageDestroy(String actName) {
        actLiveMap.put(actName, false);
    }
Register interface status in Activity

Name the current Activity. Tagnames must be unique for each Activity.

private static final String MY_ACT_NAME = "xxx1Activity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        NetworkCenter.markPageAlive(MY_ACT_NAME);
        // ...
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        NetworkCenter.markPageDestroy(MY_ACT_NAME);
        // ...
    }
OkHttpClient add interceptor

Add an interceptor to OkHttpClient to check the survival of the page in the interceptor. After checking, remove the custom header.

public static final String HEADER_ACT_NAME = "Activity-Name"; // Tag Activity interface name

    private Interceptor lifeInterceptor = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            String actName = request.header(HEADER_ACT_NAME);
            if (!TextUtils.isEmpty(actName)) {
                Log.d(TAG, "lifeInterceptor: actName: " + actName);
                Boolean actLive = actLiveMap.get(actName);
                if (actLive == null || !actLive) {
                    chain.call().cancel();
                    Log.d(TAG, "lifeInterceptor: Cancel request, actName: " + actName);
                } else {
                    Log.d(TAG, "lifeInterceptor: Initiate request, actName: " + actName);
                }
            }
            Request newRequest = request.newBuilder().removeHeader(HEADER_ACT_NAME).build();
            return chain.proceed(newRequest);
        }
    };

OkHttpClient = new OkHttpClient.Builder()
        .readTimeout(10, TimeUnit.SECONDS)
        .connectTimeout(10, TimeUnit.SECONDS)
        .addInterceptor(lifeInterceptor) // Add interceptor
        .build();

After call.cancel(), the subscribe method of Retrofit will not be used.

Add header
@GET("users/{owner}/repos")
    Observable<List<UserRepo>> userRepo(
            @Header(NetworkCenter.HEADER_ACT_NAME) @Nullable String actName,
            @Path("owner") String owner,
            @Query("sort") String sortType);

[Android Development: Framework source code analysis video reference]

Posted by unrelenting on Thu, 25 Nov 2021 18:39:11 -0800