`

OkHttp的使用简介及封装,实现更简洁的调用

阅读更多

最近将项目使用的网络请求库换成了OkHttp,体验感觉上升了好几个档次啊,-。-,之前项目是好几年前的,封装了原生的httpClient,没有实现异步请求,每次都要自己开个线程,然后再实现退出的时候把线程关了,还要实现本地缓存,啊,听起来好麻烦有木有,然后我终于受不了了,自己封装了下OkHttp(。。。其实这个是好久前写的代码,一直没机会实际运用,刚好可以当小白鼠)。。。。不废话了

1.首先,OkHttp本身是有缓存这个东西的,只是如果你不去设置,是不起作用的
.
client.setCache(new Cache(context.getCacheDir(),maxCacheSize));
.

设置缓存目录和缓存大小,OkHttp内部是使用LRU来管理缓存的
2.当然,设置了缓存和目录还是不够的,http请求总该有个过期时间吧,缓存是由HTTP消息头中的”Cache-control”来控制的,常见的取值有private、no-cache、max-age、must-revalidate等,默认为private。
下面是作用:

  • public 所有内容都将被缓存
  • private 内容只缓存到私有缓存中
  • no-cache 所有内容都不会被缓存
  • no-store 所有内容都不会被缓存到缓存或 Internet 临时文件中
  • must-revalidation/proxy-revalidation 如果缓存的内容失效,请求必须发送到服务器/代理以进行重新验证
  • max-age=xxx (xxx is numeric) 缓存的内容将在 xxx 秒后失效, 这个选项只在HTTP 1.1可用, 并如果和Last-Modified一起使用时, 优先级较高

一般来说我们用到的是no-cache和max-age比较多,既然我们要实现缓存,那么自然就要在我们的每一条的请求头里面添加这个属性,OkHttp提供了Interceptor 拦截器这个东西,做过web应该明白,就是在你一条http请求要发送之前,拦截下来,做一些处理然后再继续发送,因此,我们就可以添加一个拦截器,在请求前把Cache-control:max-age=36000添加到请求头里去。


Interceptor cacheInterceptor = new Interceptor() {
            @Override public Response intercept(Chain chain) throws IOException {
                Response originalResponse = chain.proceed(chain.request());
                return originalResponse.newBuilder()
                        .removeHeader("Pragma")//Pragma:no-cache。在HTTP/1.1协议中,它的含义和Cache-Control:no-cache相同。为了确保缓存生效
                        .header("Cache-Control", String.format("max-age=%d", maxCacheAge))//添加缓存请求头
                        .build();
            }
        };

 

 

3.嗯,差不多到这一步就已经快完成了,剩下的就是调用OkHttp的方法了。

.
Request.Builder requestBuilder = new Request.Builder().url(url).cacheControl(cacheControl);
.

一个OkHttp的请求大致是这样子的,url是必须的,然后如果我们要实现缓存,cacheControl也是必须的,OkHttp提供了CacheControl这个类,里面FORCE_CACHE 和FORCE_NETWORK分别表示只从缓存获取数据和只通过网络请求获取数据,有了前面的两步设置,这时我们是可以通过设置FORCE_CACHE 来从缓存获取数据而不通过网络获取服务器的数据的(前提是你本地要有缓存,也就是必须先通过网络请求获取到一次数据才能获取到缓存),代码没什么,就不贴了。

嗯,我们的网络请求实现本地缓存已经实现,当你网络请求失败的时候又不希望展示给用户的是一片空白,那你就可以调用本地之前的缓存了!!你别告诉我这样你就满足了,这每次都要判断是不是请求失败了,要不要请求缓存,这想想都蛋疼啊!!!

所以我对OkHttp进行封装,实现了只查询缓存,网络请求失败自动查询本地缓存等功能
支持4种不同的查询方式

*ONLY_NETWORK 只查询网络数据

*ONLY_CACHED 只查询本地缓存

*CACHED_ELSE_NETWORK 先查询本地缓存,如果本地没有,再查询网络数据

*NETWORK_ELSE_CACHED 先查询网络数据,如果没有,再查询本地缓存

支持get和post请求,默认查询方式为NETWORK_ELSE_CACHED,可通过Builder来指定默认查询方式

===================我是分隔符=================
先贴代码

 //实现一个最基本的请求方法
private Call request(Request request, Callback callback){
        if(DEBUG){
            Log.d("OKHttp",request.toString());
        }
        Call call = client.newCall(request);
        call.enqueue(callback);
        return call;
    }
//实现自己的回调,添加了onStart和onFinish方法
public abstract class Callback implements com.squareup.okhttp.Callback {
    public void onStart(){

    }
    public void onFinish(){

    }

    public abstract void onFailure(Request request, IOException e);

    public abstract void onResponse(Response response) throws IOException;
}
//定义一个公用的方法,实现最基本的封装,无论是post还是get都适用
private void request(String url, String method, RequestBody requestBody, final CacheControl cacheControl, Headers headers,Object tag ,final Callback callback){
        final Request.Builder requestBuilder = new Request.Builder().url(url).cacheControl(cacheControl);
        if(headers!=null){
            requestBuilder.headers(headers);
        }
        requestBuilder.method(method,requestBody);//如果是get请求,这里requestBody就应该传个null
        requestBuilder.tag(tag==null?url:tag);//OkHttp的tag是对请求的标志,可以通过tag来获取到请求和取消请求,这里如果你不传,就将当前url设置为tag

        final Request request = requestBuilder.build();
        request(request,new Callback() {//这里是回调

            @Override
            public void onStart() {
                if(callback!=null){
                    callback.onStart();
                }
            }

            @Override
            public void onFinish() {
                if(callback!=null){
                    callback.onFinish();
                }
            }

            @Override
            public void onFailure(Request request, IOException e) {
                if(callback!=null){
                    callback.onFailure(request,e);
                    callback.onFinish();
                }
            }

            @Override
            public void onResponse(Response response) throws IOException {
                if(response.code()==504){//OkHttp如果缓存请求不到是会报504的
                    if(CacheControl.FORCE_CACHE == cacheControl){
                        if(callback!=null){
                            callback.onFailure(request,new IOException("cached not found"));
                            callback.onFinish();
                        }
                        return;
                    }
                }
                if(callback!=null){
                    callback.onResponse(response);
                    callback.onFinish();
                }
            }
        });
    }
//实现只请求网络和只请求缓存的方法
 public void requestFromNetwork(final String url,String method,RequestBody requestBody, Headers headers,Object tag,final Callback callback){
        request(url,method,requestBody,CacheControl.FORCE_NETWORK,headers,tag,callback);
    }

    public void requestFromCached(String url,String method,RequestBody requestBody,Headers headers ,Object tag,final Callback callback){
        request(url,method,requestBody,CacheControl.FORCE_CACHE,headers,tag,callback);
    }

重点来了!!
定义了4种请求类型
*ONLY_NETWORK 只查询网络数据

*ONLY_CACHED 只查询本地缓存

*CACHED_ELSE_NETWORK 先查询本地缓存,如果本地没有,再查询网络数据

*NETWORK_ELSE_CACHED 先查询网络数据,如果没有,再查询本地缓存

前两种都没什么好说的,直接调用写好的两个方法requestFromNetwork和requestFromCached就行了
后面两种:
1.CACHED_ELSE_NETWORK 先查询本地缓存,如果本地没有,再查询网络数据,我们就需要自己再传一个Callback c2回调了,当回调执行成功的时候,我们直接就调用方法的回调的onResponse就行,其余情况我们就需要查询网络的数据,到了这一步,说明本地没有缓存了,所以直接调用requestFromNetwork就行

 public void request(final String url, final CacheType cacheType, final String method, final RequestBody requestBody, final Headers headers, final Object tag , final Callback callback){
        if(callback!=null)callback.onStart();
        switch (cacheType){
            case ONLY_NETWORK://只查询网络数据
                requestFromNetwork(url,method,requestBody,headers,tag,callback);
                break;
            case ONLY_CACHED://只查询本地缓存
                requestFromCached(url,method,requestBody,headers,tag,callback);
                break;
            case CACHED_ELSE_NETWORK:
                requestFromCached(url,method,requestBody,headers,tag, new Callback() {
                    @Override
                    public void onStart() {
                        if(callback!=null){
                            callback.onStart();
                        }
                    }

                    @Override
                    public void onFinish() {
                        if(callback!=null){
                            callback.onFinish();
                        }
                    }

                    @Override
                    public void onFailure(Request request, IOException e) {
                        requestFromNetwork(url,method,requestBody,headers,tag,callback);
                    }

                    @Override
                    public void onResponse(Response response) throws IOException {
                        if(response.code()==200){//response.isSuccessful()OkHttp是有这个方法判断请求是否成功的,但判断的方法是根据状态码是否是20开头(200,201,202,203等,具体区别就不在这里描述了,有兴趣的百度)来判断的,但只有200返回的数据才是我们想要的
                            if(callback!=null){
                                callback.onResponse(response);
                                callback.onFinish();
                            }
                        }else{
                            requestFromNetwork(url,method,requestBody,headers,tag,callback);
                        }
                    }
                });
                break;
            case NETWORK_ELSE_CACHED:
                requestFromNetwork(url,method,requestBody,headers,tag, new Callback() {
                    @Override
                    public void onStart() {
                        if(callback!=null){
                            callback.onStart();
                        }
                    }

                    @Override
                    public void onFinish() {
                        if(callback!=null){
                            callback.onFinish();
                        }
                    }

                    @Override
                    public void onFailure(Request request, IOException e) {
                        requestFromCached(url,method,requestBody,headers,tag,callback);
                    }

                    @Override
                    public void onResponse(Response response) throws IOException {
                        if(response.code()==200){
                            if(callback!=null){
                                callback.onResponse(response);
                                callback.onFinish();
                            }
                        }else{
                            requestFromCached(url,method,requestBody,headers,tag,callback);
                        }
                    }
                });
                break;
        }
    }
  • 1

2.NETWORK_ELSE_CACHED 这个和CACHED_ELSE_NETWORK 实现原理是一样的,就略过。

。。。。。写得好累



!!!你以为这样就完了?还要有json解析啊,这年头,还用自带的json解析有点low
(。。。。。之前我是用自带的)


目前json解析的有fastJson、jackJson(这个包比较大,不怎么推荐)、Gson,我这里就用Gson了
首先,再添加一个回调的类


public abstract class JsonCallback<T> {
    public abstract void onFailure(Request request, Exception e);
    public abstract void onResponse(T object) throws IOException;

    public void onStart(){

    }
    public void onFinish(){

    }

//这个才是重点,获取Json的类型,因为数据可能集合也可能是Object
    Type getType(){
        Type type = ((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        if(type instanceof Class){
            return type;//如果是Object直接返回
        }else{
            return new TypeToken<T>(){}.getType();//如果是集合,获取集合的类型map或list
        }
    }
}

 

 

接下来就是对返回的数据进行解析了

//这里只贴部分关键代码
 public void request(final String url, final CacheType cacheType, final String method, final RequestBody requestBody, final Headers headers,Object tag,final JsonCallback callback)

//在onResponse进行解析,具体看文章结尾源码
@Override
public void onResponse(Response response) throws IOException {
     if(response.isSuccessful() && callback!=null){
         String jsonString = response.body().string();;
         if(!TextUtils.isEmpty(jsonString)){
             Object result = null;
             try {
                 result =  gson.fromJson(jsonString,callback.getType());//直接调用Gson解析
                 callback.onResponse(result);
                 callback.onFinish();
             } catch (JsonSyntaxException e) {
                 callback.onFailure(null,new Exception("json string parse error :"+e.toString()));
                 callback.onFinish();
                 e.printStackTrace();
             }

         }else{
             callback.onFailure(null,new Exception("json string may be null"));
             callback.onFinish();
         }
     }
 }

嗯,写到这里终于完了!!!!下篇写OkHttp的文件下载
源码戳下面链接,几个点start给个赞啊,写了好多重载函数很累的!!!
compile ‘git.dzc:okhttputilslib:1.0.4’ 代码上传到了mavenCentral,Android Studio直接这样就可以引用
https://github.com/duzechao/OKHttpUtils

<!-- Baidu Button BEGIN -->
0
0
分享到:
评论

相关推荐

    Android-对Okhttp3进行二次封装

    本文将深入探讨如何对Okhttp3进行二次封装,以实现更便捷、功能丰富的API,包括POST、GET、PATCH、PUT、DELETE等HTTP方法,文件上传与下载,请求取消,以及支持Raw、Json、Gson格式的响应处理,同时还会涉及后台下载...

    封装的okhttp demo

    以上就是关于封装的OkHttp Demo的详细解析,通过这个Demo,开发者可以轻松地在商业项目中集成并使用OkHttp,从而实现高效、稳定的网络通信。记得在实际应用中,根据项目需求调整和扩展这个Demo,以达到最佳效果。

    简单封装使用OkHttp3

    本篇文章将详细探讨如何简单封装使用OkHttp3,以实现高效、便捷的网络调用。 首先,我们需要在项目中引入OkHttp3库。在build.gradle文件中添加依赖: ```groovy dependencies { implementation '...

    Okhttp框架post json封装

    **正文** OkHttp框架是Square公司开发的一款高效的HTTP客户端库,广泛应用于Android开发中,它以其优秀的性能、简单...此外,对于网络请求的回调,可以结合现代的编程范式,如协程或RxJava,来实现更优雅的异步处理。

    okhttp框架封装

    本篇文章将深入探讨如何对OkHttp进行封装,以实现更灵活、易用的接口链式请求。 **一、OkHttp基础** OkHttp的核心概念包括`OkHttpClient`、`Request`和`Response`。`OkHttpClient`是整个框架的入口,负责配置网络...

    android Retrofit+OKhttp实现接口调用

    下面将详细介绍如何在Android中使用Retrofit+OkHttp实现接口调用,并探讨其基础概念、使用方法以及如何创建一个基础的接口调用类。 1. **Retrofit简介** Retrofit是由Square公司开发的一个Android和Java的网络请求...

    okhttp二次回调封装Demo

    通过以上这些知识点的封装,开发者可以更加便捷地使用OkHttp进行网络请求,而无需关心底层的实现细节。这种封装不仅降低了学习成本,也提高了代码的可维护性和一致性。对于初学者来说,理解并实践这样的封装案例,有...

    高度封装的OkHttp

    总的来说,"高度封装的OkHttp"为开发者提供了一个简洁、高效的网络请求解决方案,无论是在小型项目还是大型系统中,都能发挥出色的作用。通过学习和掌握OkHttp的使用,可以显著提升开发效率,优化应用的网络性能。

    自己封装的OKHttp工具类,粘贴后直调用接

    【标题】:自己封装的OKHttp工具类,粘贴后直调用接 【知识点解析】: OKHttp是Android平台上一款高效、易用的网络请求库,由Square公司开发。它以其优秀的性能、低资源消耗以及强大的功能而受到开发者们的广泛...

    okhttp二次封装

    在本案例中,描述提到了"注解处理器方式实现retrofit",这表明是将OkHttp与Retrofit结合,利用注解处理器简化接口调用的过程。 Retrofit是由Square公司开发的一个Java和Kotlin的类型安全的HTTP客户端,它允许我们...

    封装好的OKHTTP

    在HTTP客户端库的使用中,封装可以简化API调用,使代码更清晰,更易于理解和维护。封装好的OKHTTP demo允许开发者无需深入了解OKHTTP的底层机制,只需关注业务逻辑,提高了开发效率。 **使用步骤** 1. **导入依赖*...

    【Android】RxJava2+Retrofit2+OkHttp3的基础、封装和项目中的使用

    在Android中,RxJava可以与Retrofit结合使用,通过Observables处理网络请求的结果,支持链式调用,使得代码更加简洁和易读。 OkHttp3是一个高效的HTTP客户端,它提供了比Android自带的HttpURLConnection更优秀的...

    OkHttp的二次封装的

    总的来说,OkHttp的二次封装是提高代码复用性和项目可维护性的重要手段,通过封装网络请求和数据解析,可以降低开发难度,使开发者更专注于业务逻辑的实现。同时,确保在主线程中处理返回数据,是保证用户体验的关键...

    RxJava+Retrofit2+Okhttp3经典封装demo

    这个"RxJava+Retrofit2+Okhttp3经典封装demo"将展示如何整合这三个库,实现优雅的异步网络调用。 RxJava是一个响应式编程库,它通过观察者模式和流的概念,简化了事件处理和数据管理。在Android中,RxJava常用于...

    okhttp的封装

    封装 OkHttp 主要目的是为了使其更符合项目需求,提高代码可读性和可维护性。以下是一些常见的封装策略: 1. **构建统一的请求接口**:创建一个 RequestBuilder 类,将请求方法(GET、POST等)、URL、参数、Header ...

    使用OKhttp,Rxjava封装的mvp模式架构

    1. **链式调用**:通过操作符链,可以简洁地描述复杂的异步操作。 2. **统一处理**:统一处理各种类型的事件,如点击事件、网络请求、定时任务等。 3. **线程控制**:通过Scheduler,轻松实现UI线程和后台线程间的...

    OKHttp网络请求超简单封装DEMO

    总之,OKHttp的简单封装主要是围绕OkHttpClient的构建和Call对象的使用展开,通过提供统一的接口,使网络请求变得更加方便。结合提供的DEMO,开发者可以快速上手并根据项目需求进一步扩展功能。

    okHttp封装库 Eclipse版本

    8. **安全**:OkHttp 强调安全性,支持 HTTPS 和 TLS,可以通过配置证书来实现更高级别的加密通信。 在提供的 `OkhttpDemo` 文件中,很可能是包含了一个简单的示例程序,演示如何使用 OkHttp 发送 GET 和 POST 请求...

    okHttp+AsyncTask封装请求框架不需手动解析

    【标题】:OkHttp+AsyncTask封装请求框架不需手动解析 在移动应用开发中,网络请求是必不可少的一部分。OkHttp是一款高效的HTTP客户端库,它以其简洁的API、优秀的性能和连接管理而受到广泛欢迎。而Android中的...

    Android-KHttp利用KotlinDSL封装OKHttp3

    总的来说,KHttp通过Kotlin DSL封装OKHttp3,实现了优雅的API设计,让Android开发者在进行网络请求时,能够写出更加简洁、易读的代码,提升了开发效率。结合实际项目中的需求,你可以根据KHttp提供的基础,进行...

Global site tag (gtag.js) - Google Analytics