• Android OkHttp + Retrofit 取消请求的方法


    Android 2020

    本文链接

    前言

    在某一个界面,用户发起了一个网络请求,因为某种原因用户在网络请求完成前离开了当前界面,比较好的做法是取消这个网络请求。对于OkHttp来说,具体是调用Callcancel方法。

    如何找到这一个网络请求并取消掉它呢?

    操作大致分为3步。第一步,在建立请求时,给请求(request)添加标记;第二步,根据标记,找到请求;最后,取消这个请求。

    OkHttp中的tag

    要取消一个请求,OkHttp中可以使用cancel方法,参考

    OkHttp的request对象有tag。可以根据tag来标示请求。参考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();
        }
    
    

    Retrofit中并没有显示地提供取消请求的接口。2018年时Retrofit仍未提供直接访问call对象的方法
    那么如何找到目标网络请求呢?

    Retrofit加入自定义header

    给每个与页面(Activity,Fragment)相关的request加入自定义header,参考
    给OkHttpClient添加拦截器。标记出页面的生存状态。如果页面销毁了,则取消对应的request。

    以GithubOnAndroid项目为例,https://github.com/RustFisher/GithubOnAndroid

    添加标记

    持有一个ConcurrentHashMap<String, Boolean>来标记页面存活状态。

        private static ConcurrentHashMap<String, Boolean> 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<List<UserRepo>> userRepo(
                @Header(NetworkCenter.HEADER_ACT_NAME) @Nullable String actName,
                @Path("owner") String owner,
                @Query("sort") String sortType);
    
  • 相关阅读:
    windows service 安装和卸载指令
    jackson 进行json与java对象转换 之四
    jackson 进行json与java对象转换 之三
    jackson 进行json与java对象转换 之二
    jackson 进行json与java对象转换 之一
    jackson2.x与Jackson1.9的比较
    判断Integer值相等不能用==
    java:String使用equals和==比较的区别
    Java中自定义枚举(Enum)项的值,可设置为指定的值
    Java enum(枚举)使用详解之四
  • 原文地址:https://www.cnblogs.com/rustfisher/p/11680054.html
Copyright © 2020-2023  润新知