本文最后更新于 2023年4月15日 下午
                  
                
              
            
            
              
                
                本文链接 
前言 在某一个界面,用户发起了一个网络请求,因为某种原因用户在网络请求完成前离开了当前界面,比较好的做法是取消这个网络请求。对于OkHttp来说,具体是调用Call的cancel方法。
如何找到这一个网络请求并取消掉它呢?
操作大致分为3步。第一步,在建立请求时,给请求(request)添加标记;第二步,根据标记,找到请求;最后,取消这个请求。
OkHttp中的tag 要取消一个请求,OkHttp中可以使用cancel方法,参考 。
OkHttp的request对象有tag。可以根据tag来标示请求。参考Stack Overflow 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 Request  request  =  new  Request .Builder()."requestKey" ).build();for  (Call call : mHttpClient.dispatcher().queuedCalls()) {if  (call.request().tag().equals("requestKey" ))for  (Call call : mHttpClient.dispatcher().runningCalls()) {if  (call.request().tag().equals("requestKey" ))
Retrofit中并没有显示地提供取消请求的接口。2018年时Retrofit仍未提供直接访问call对象的方法 
给每个与页面(Activity,Fragment)相关的request加入自定义header,参考 。
以GithubOnAndroid项目为例,https://github.com/RustFisher/GithubOnAndroid 
添加标记 持有一个ConcurrentHashMap<String, Boolean>来标记页面存活状态。
1 2 3 4 5 6 7 8 9 private  static  ConcurrentHashMap<String, Boolean> actLiveMap = new  ConcurrentHashMap <>(); public  static  void  markPageAlive (String actName)  {true );public  static  void  markPageDestroy (String actName)  {false );
Activity中登记界面状态 给当前Activity起名字。每个Activity的标记名必须唯一。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 private  static  final  String  MY_ACT_NAME  =  "xxx1Activity" ;@Override protected  void  onCreate (Bundle savedInstanceState)  {super .onCreate(savedInstanceState);@Override protected  void  onDestroy ()  {super .onDestroy();
OkHttpClient添加拦截器 给OkHttpClient添加拦截器,在拦截器中检查页面的存活情况。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28     public  static  final  String  HEADER_ACT_NAME  =  "Activity-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)) {"lifeInterceptor: actName: "  + actName);Boolean  actLive  =  actLiveMap.get(actName);if  (actLive == null  || !actLive) {"lifeInterceptor: 取消请求, actName: "  + actName);else  {"lifeInterceptor: 发起请求, actName: "  + actName);Request  newRequest  =  request.newBuilder().removeHeader(HEADER_ACT_NAME).build();return  chain.proceed(newRequest);new  OkHttpClient .Builder()10 , TimeUnit.SECONDS)10 , TimeUnit.SECONDS)
call.cancel()后,不会再走Retrofit的subscribe方法。
1 2 3 4 5 @GET("users/{owner}/repos") userRepo (         @Header(NetworkCenter.HEADER_ACT_NAME)  @Nullable  String actName,         @Path("owner")  String owner,         @Query("sort")  String sortType) ;
更多请参考:
Android OkHttp + Retrofit 使用示例 
Android OkHttp + Retrofit 取消请求的方法 
Android OkHttp + Retrofit 下载文件与进度监听 
Android OkHttp + Retrofit 断点续传