Android入门教程 | OkHttp + Retrofit 取消请求的方法

在某一个界面,用户发起了一个网络请求,因为某种原因用户在网络请求完成前离开了当前界面,比较好的做法是取消这个网络请求。如何找到这一个网络请求并取消掉它呢?
前言 在某一个界面,用户发起了一个网络请求,因为某种原因用户在网络请求完成前离开了当前界面,比较好的做法是取消这个网络请求。对于 OkHttp 来说,具体是调用Callcancel方法。
如何找到这一个网络请求并取消掉它呢?
操作大致分为3步:

  • 第一步,在建立请求时,给请求(request)添加标记;
  • 第二步,根据标记,找到请求;
  • 最后,取消这个请求。
OkHttp中的tag 要取消一个请求,OkHttp中可以使用 cancel 方法。
OkHttp 的 request 对象有 tag。可以根据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(); }

Retrofit 中并没有显示地提供取消请求的接口。那么如何找到目标网络请求呢?
Retrofit加入自定义header 给每个与页面(Activity,Fragment)相关的 request 加入自定义header。 给 OkHttpClient添加拦截器。标记出页面的生存状态。如果页面销毁了,则取消对应的request。
以 GithubOnAndroid 项目为例
添加标记 持有一个 ConcurrentHashMap 来标记页面存活状态。
private static ConcurrentHashMap actLiveMap = new ConcurrentHashMap<>(); // 标记Activity是否存活public static void markPageAlive(String actName) { actLiveMap.put(actName, true); }public static void markPageDestroy(String actName) { actLiveMap.put(actName, false); }

Activity中登记界面状态 给当前 Activity 起名字。每个 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 添加拦截器 给 OkHttpClient 添加拦截器,在拦截器中检查页面的存活情况。 检查后,把这个自定义header移除掉。
public static final String HEADER_ACT_NAME = "Activity-Name"; // 标记Activity界面名字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: 取消请求, actName: " + actName); } else { Log.d(TAG, "lifeInterceptor: 发起请求, 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) // 添加拦截器 .build();

call.cancel() 后,不会再走 Retrofit 的 subscribe 方法。
添加 header
@GET("users/{owner}/repos") Observable> userRepo( @Header(NetworkCenter.HEADER_ACT_NAME) @Nullable String actName, @Path("owner") String owner, @Query("sort") String sortType);

【Android入门教程 | OkHttp + Retrofit 取消请求的方法】【Android开发:框架源码解析视频参考】

    推荐阅读