The original link

preface

In one interface, a user initiates a network request, but for some reason the user leaves the current interface before the network request is completed. It is a good practice to cancel the network request. In the case of OkHttp, this is the Call cancel method.

How do you find a network request and cancel it?

The tag OkHttp

To cancel a request, OkHttp uses the cancel method, see.

The OkHttp request object has a tag. Requests can be identified by tag. See Stack Overflow.

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

Copy the code

Retrofit does not explicitly provide an interface to cancel requests. In 2018 Retrofit didn’t provide direct access to call objects so how do you find the target network request?

Retrofit adds custom headers

Add custom headers to every Activity/Fragment request. Add an interceptor to OkHttpClient. Mark the living state of the page. If the page is destroyed, cancel the corresponding request.

Take the GithubOnAndroid project for example, github.com/RustFisher/…

Add tag

Holds a ConcurrentHashMap<String, Boolean> to mark the page survival status.

    private static ConcurrentHashMap<String, Boolean> actLiveMap = new ConcurrentHashMap<>(); // Marks 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);
    }
Copy the code

Register the interface state in the Activity

Give the current Activity a name. The tag name for each Activity must be unique.

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(a) {
        super.onDestroy();
        NetworkCenter.markPageDestroy(MY_ACT_NAME);
        // ...
    }
Copy the code

OkHttpClient adds an interceptor

Add an interceptor to OkHttpClient that checks for page survival. After checking, remove the custom header.

    public static final String HEADER_ACT_NAME = "Activity-Name"; // Mark the name of the Activity interface

    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: initiates a request, actName:" + actName);
                }
            }
            Request newRequest = request.newBuilder().removeHeader(HEADER_ACT_NAME).build();
            returnchain.proceed(newRequest); }}; OkHttpClient =new OkHttpClient.Builder()
        .readTimeout(10, TimeUnit.SECONDS)
        .connectTimeout(10, TimeUnit.SECONDS)
        .addInterceptor(lifeInterceptor) // Add interceptor
        .build();
Copy the code

Retrofit’s subscribe method is no longer invoked after call.cancel().

Add the 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);
Copy the code

Relevant link rustfisher.com/2019/06/26/…