热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

OkHttp怎么用

这篇文章主要为大家展示了“OkHttp怎么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“OkHttp

这篇文章主要为大家展示了“OkHttp怎么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“OkHttp怎么用”这篇文章吧。

前言

先看Android中网络请求的进化图:

OkHttp怎么用

HttpURLConnection,Apache HTTP  Client,Volley到现在的OKHttp,可谓天外有天,人外有人。为什么OKHttp会这么火呢,相信下面的介绍会告诉你答案。

OKHttp的简介

首先,给出OKHttp的项目地址:https://github.com/square/okhttp

Android为我们提供了两种HTTP交互的方式: HttpURLConnection 和 Apache HTTP  Client,虽然两者都支持HTTPS,流的上传和下载,配置超时,IPv6和连接池,已足够满足我们各种HTTP请求的需求。但更高效的使用HTTP可以让您的应用运行更快、更节省流量。而OkHttp库就是为此而生。  OkHttp是一个高效的HTTP库:

1.支持 SPDY ,共享同一个Socket来处理同一个服务器的所有请求

2.如果SPDY不可用,则通过连接池来减少请求延时

3.无缝的支持GZIP来减少数据流量

1.缓存响应数据来减少重复的网络请求

2.一般的get请求

3.一般的post请求

4.基于Http的文件上传

5.文件下载

6.加载图片

7.支持请求回调,直接返回对象、对象集合

8.支持session的保持

OkHttp会从很多常用的连接问题中自动恢复。如果您的服务器配置了多个IP地址,当***个IP连接失败的时候,会自动尝试下一个IP。OkHttp还处理了代理服务器问题和SSL握手失败问题。(并发)  使用 OkHttp 无需重写您程序中的网络代码。OkHttp实现了几乎和java.net.HttpURLConnection一样的API。如果您用了  Apache HttpClient,则OkHttp也提供了一个对应的okhttp-apache 模块。  从上面的简单介绍中可以知道,虽然在编程上面并不会简洁很多,但是OKHttp内部的一些功能能够帮助我们自动完成一些很复杂的操作,笔者个人认为***的卖点就是大大节省用户的流量。

OKHttp的基本使用

1、在Gradle中引入CardView的依赖库。

compile 'com.squareup.okhttp:okhttp:3.8.0'

2、OKHttp在使用之前,首先要了解下面几个比较核心的类以及它的功能。

  • OkHttpClient 客户端对象

  • Request是OkHttp中访问的请求,Post请求中需要包含RequestBody

  • Builder是辅助类,用于生产对象

  • Response即OkHttp中的响应,响应中可以得到返回是否成功,返回数据

  • MediaType 数据类型,用来表明是JSON等一系列格式

  • RequestBody 请求数据,在Post请求中用到

  • client.newCall(request).execute()是同步的请求方法

  • client.newCall(request).enqueue(Callback  callBack)是异步的请求方法,但是Callback里面的代码是执行在子线程的,因此不能更新UI。

3、OKHttp的基本使用步骤(以POST方式从服务器取JSON数据为例)

  • 创建OkHttpClient对象,官方文档要求我们***使用单例模式,在后文对OKHttp进行封装的时候会提到。

  • 如果是post请求的话,需要通过FormEncodingBuilder创建RequestBody对象,指定需要post传进去的参数。get请求则不用。

  • 创建Request对象,这个对象是请求对象,需要指定URL。post请求的时候需要指定RequestBody对象,get请求则不用。

  • 调用OkHttpClient的newCall方法,把Request对象传进去,然后执行execute或者enqueue方法,两者的区别在上文已提到。在CallBack中的onResponse方法就可以做你需要做的事。onResponse回调的参数是response,一般情况下,比如我们希望获得返回的字符串,可以通过response.body().string()获取;如果希望获得返回的二进制字节数组,则调用response.body().bytes();如果你想拿到返回的inputStream,则调用response.body().byteStream()看到这,你可能会奇怪,竟然还能拿到返回的inputStream,看到这个最起码能意识到一点,这里支持大文件下载,有inputStream我们就可以通过IO的方式写文件。不过也说明一个问题,这个onResponse执行的线程并不是UI线程。的确是的,如果你希望操作控件,还是需要使用handler等。

OkHttpClient client = new OkHttpClient();      RequestBody body = new FormEncodingBuilder()             .add("type", "1")             .build();    Request request = new Request.Builder()             .url(Constants.URL_BANNER)             .post(body)             .build();      client.newCall(request).enqueue(new Callback() {         @Override             public void onFailure(Request request, IOException e) {          }          @Override             public void onResponse(Response response) throws IOException {                         if (response.isSuccessful()) {                  android.os.Message msg = new Message();                 msg.what = 1;                 msg.obj = response.body().string();                 mHandler.sendMessage(msg);             }         }     });

这里只是一个简单post请求,从服务器获取数据的介绍,至于get请求只不过是去掉RequestBody对象而已。至于如何向服务器提交数据,可以在熟悉上面的基本用法之后查阅官方的WIKI(GitHub的介绍文档)。

OKHttp的简单封装

回顾上面的代码,试想一下如果每次请求都写这么多重复代码,这样会严重降低开发效率,因此需要对OKHttp进行封装。对代码进行封装是我们最为面向对象程序员的基本素养,减少重复代码,降低维护难度以及成本。

GitHub上也有对OKHttp进行过封装,叫做OKHttpUtils。不过这里我们自己动手,一起来学习一下如何进行封装。具体的注意点有下面几点:

1、首先,OKHttp官方要求我们***用单例模式去使用OKHttpClient类的,因此我们自定义一个OKHttpHelper类,并且使用单例模式。

2、对get以及post方法进行封装,主要的思想是把共同的代码抽取出来,例如代码中被抽取出来的request方法。

3、对外公开一些静态方法,包括get和post方法等。

4、Callback基类,对OKHttp的回调进行封装。这个类用里面有一个type,是方便回调中使用Gson对JSON进行解析的封装。使用Callback的时候只需要在泛型中传入类似Data  、List即可以方便地使用JSON。

5、由于原来的回调不在主线程,因此我们需要使用Handler来将回调放入主线程。

其余的可以参照代码,有详细注释。

/**  * 这个类用来辅助OKHttp  */public class OkHttpHelper {    /**      * 采用单例模式使用OkHttpClient      */     private static OkHttpHelper mOkHttpHelperInstance;         private static OkHttpClient mClientInstance;         private Handler mHandler;         private Gson mGson;    /**      * 单例模式,私有构造函数,构造函数里面进行一些初始化      */     private OkHttpHelper() {         mClientInstance = new OkHttpClient();          mClientInstance.setConnectTimeout(10, TimeUnit.SECONDS);         mClientInstance.setReadTimeout(10, TimeUnit.SECONDS);         mClientInstance.setWriteTimeout(30, TimeUnit.SECONDS);         mGson = new Gson();          mHandler = new Handler(Looper.getMainLooper());     }    /**      * 获取实例      *      * @return      */     public static OkHttpHelper getinstance() {                 if (mOkHttpHelperInstance == null) {                         synchronized (OkHttpHelper.class) {                                 if (mOkHttpHelperInstance == null) {                     mOkHttpHelperInstance = new OkHttpHelper();                 }             }         }        return mOkHttpHelperInstance;     }    /**      * 封装一个request方法,不管post或者get方法中都会用到      */     public void request(final Request request, final BaseCallback callback) {        //在请求之前所做的事,比如弹出对话框等         callback.onRequestBefore();          mClientInstance.newCall(request).enqueue(new Callback() {                         @Override             public void onFailure(Request request, IOException e) {                //返回失败                 callbackFailure(request, callback, e);             }            @Override             public void onResponse(Response response) throws IOException {                                 if (response.isSuccessful()) {                    //返回成功回调                     String resString = response.body().string();                                     if (callback.mType == String.class) {                        //如果我们需要返回String类型                         callbackSuccess(response, resString, callback);                     } else {                        //如果返回的是其他类型,则利用Gson去解析                         try {                             Object o = mGson.fromJson(resString, callback.mType);                             callbackSuccess(response, o, callback);                         } catch (JsonParseException e) {                             e.printStackTrace();                             callbackError(response, callback, e);                         }                     }                  } else {                    //返回错误                     callbackError(response, callback, null);                 }             }         });     }    /**      * 在主线程中执行的回调      *      * @param response      * @param resString      * @param callback      */     private void callbackSuccess(final Response response, final Object o, final BaseCallback callback) {         mHandler.post(new Runnable() {                         @Override             public void run() {                 callback.onSuccess(response, o);             }         });     }    /**      * 在主线程中执行的回调      * @param response      * @param callback      * @param e      */     private void callbackError(final Response response, final BaseCallback callback, final Exception e) {         mHandler.post(new Runnable() {                         @Override             public void run() {                 callback.onError(response, response.code(), e);             }         });     }    /**      * 在主线程中执行的回调      * @param request      * @param callback      * @param e      */     private void callbackFailure(final Request request, final BaseCallback callback, final Exception e) {         mHandler.post(new Runnable() {                         @Override             public void run() {                 callback.onFailure(request, e);             }         });     }    /**      * 对外公开的get方法      *      * @param url      * @param callback      */     public void get(String url, BaseCallback callback) {         Request request = buildRequest(url, null, HttpMethodType.GET);         request(request, callback);     }    /**      * 对外公开的post方法      *      * @param url      * @param params      * @param callback      */     public void post(String url, Map params, BaseCallback callback) {         Request request = buildRequest(url, params, HttpMethodType.POST);         request(request, callback);     }    /**      * 构建请求对象      *      * @param url      * @param params      * @param type      * @return      */     private Request buildRequest(String url, Map params, HttpMethodType type) {         Request.Builder builder = new Request.Builder();         builder.url(url);                     if (type == HttpMethodType.GET) {             builder.get();         } else if (type == HttpMethodType.POST) {             builder.post(buildRequestBody(params));         }        return builder.build();     }    /**      * 通过Map的键值对构建请求对象的body      *      * @param params      * @return      */     private RequestBody buildRequestBody(Map params) {          FormEncodingBuilder builder = new FormEncodingBuilder();                     if (params != null) {                             for (Map.Entry entity : params.entrySet()) {                 builder.add(entity.getKey(), entity.getValue());             }         }        return builder.build();     }    /**      * 这个枚举用于指明是哪一种提交方式      */     enum HttpMethodType {         GET,         POST     }  }

回调的封装

package com.nan.cnshop.http;  import com.google.gson.internal.$Gson$Types; import com.squareup.okhttp.Request; import com.squareup.okhttp.Response;  import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type;/**  * 基本的回调  */public abstract class BaseCallback {    /**      * type用于方便JSON的解析      */     public Type mType;    /**      * 把type转换成对应的类,这里不用看明白也行。      *      * @param subclass      * @return      */     static Type getSuperclassTypeParameter(Class subclass) {         Type superclass = subclass.getGenericSuperclass();                 if (superclass instanceof Class) {                         throw new RuntimeException("Missing type parameter.");         }         ParameterizedType parameterized = (ParameterizedType) superclass;                     return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);     }    /**      * 构造的时候获得type的class      */     public BaseCallback() {         mType = getSuperclassTypeParameter(getClass());     }    /**      * 请求之前调用      */     public abstract void onRequestBefore();          /**      * 请求失败调用(网络问题)      *      * @param request      * @param e      */     public abstract void onFailure(Request request, Exception e);          /**      * 请求成功而且没有错误的时候调用      *      * @param response      * @param t      */     public abstract void onSuccess(Response response, T t);          /**      * 请求成功但是有错误的时候调用,例如Gson解析错误等      *      * @param response      * @param errorCode      * @param e      */     public abstract void onError(Response response, int errorCode, Exception e);  }

OKHttp封装之后的使用

如下面的代码所示。首先得到OkHttpHelper的单例,然后调用get方法就可以了。由于继承了Gson,因此需要在BaseCallback的泛型中传入JSON对应的数据类型,笔者这里是List。***在onSuccess方法中做我们想要做的事情就可以了。

mHttpHelper=OkHttpHelper.getinstance(); mHttpHelper.get(Constants.URL_BANNER, new BaseCallback>() {         @Override     public void onRequestBefore() {      }    @Override     public void onFailure(Request request, Exception e) {      }    @Override     public void onSuccess(Response response, List banners) {         initBanners(banners);     }    @Override     public void onError(Response response, int errorCode, Exception e) {      } });

是不是觉得封装之后OKHttp的使用变得很简单呢,这就是封装的强大之处,好了今天的笔记到此为止。

以上是“OkHttp怎么用”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程笔记行业资讯频道!


推荐阅读
  • Retrofit+Rxjava+OkHttp
    为什么80%的码农都做不了架构师?参考:http:duanyytop.github.io20160806Retrofit%E7%94%A8%E6% ... [详细]
  • 本文介绍了OkHttp3的基本使用和特性,包括支持HTTP/2、连接池、GZIP压缩、缓存等功能。同时还提到了OkHttp3的适用平台和源码阅读计划。文章还介绍了OkHttp3的请求/响应API的设计和使用方式,包括阻塞式的同步请求和带回调的异步请求。 ... [详细]
  • 0x00端口渗透端口扫描端口的指纹信息(版本信息)端口所对应运行的服务常见的默认端口号.尝试弱口令端口爆破hydra端口弱口令NTScanHs ... [详细]
  • 美团Android 岗3次挂了,这次终于成功拿下!
    美团Android岗3次挂了,这次终于成功拿下!-面试流程自我介绍回答问题————(详情看下面的攻略)前面会问你很多技术问题,从简单到难,直到问到你打不出来就会又问其他部分的,也是 ... [详细]
  • android之OkHttpClient通信OkHttpClient用法1:自定义缓存OkHttpClienthttpclientnewOkHttpClient.Builder() ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • 本文介绍了使用AJAX的POST请求实现数据修改功能的方法。通过ajax-post技术,可以实现在输入某个id后,通过ajax技术调用post.jsp修改具有该id记录的姓名的值。文章还提到了AJAX的概念和作用,以及使用async参数和open()方法的注意事项。同时强调了不推荐使用async=false的情况,并解释了JavaScript等待服务器响应的机制。 ... [详细]
  • 本文介绍了关于apache、phpmyadmin、mysql、php、emacs、path等知识点,以及如何搭建php环境。文章提供了详细的安装步骤和所需软件列表,希望能帮助读者解决与LAMP相关的技术问题。 ... [详细]
  • Android系统移植与调试之如何修改Android设备状态条上音量加减键在横竖屏切换的时候的显示于隐藏
    本文介绍了如何修改Android设备状态条上音量加减键在横竖屏切换时的显示与隐藏。通过修改系统文件system_bar.xml实现了该功能,并分享了解决思路和经验。 ... [详细]
  • 标题: ... [详细]
  • 本文介绍了一些Java开发项目管理工具及其配置教程,包括团队协同工具worktil,版本管理工具GitLab,自动化构建工具Jenkins,项目管理工具Maven和Maven私服Nexus,以及Mybatis的安装和代码自动生成工具。提供了相关链接供读者参考。 ... [详细]
  • 一句话解决高并发的核心原则
    本文介绍了解决高并发的核心原则,即将用户访问请求尽量往前推,避免访问CDN、静态服务器、动态服务器、数据库和存储,从而实现高性能、高并发、高可扩展的网站架构。同时提到了Google的成功案例,以及适用于千万级别PV站和亿级PV网站的架构层次。 ... [详细]
  • Android日历提醒软件开源项目分享及使用教程
    本文介绍了一款名为Android日历提醒软件的开源项目,作者分享了该项目的代码和使用教程,并提供了GitHub项目地址。文章详细介绍了该软件的主界面风格、日程信息的分类查看功能,以及添加日程提醒和查看详情的界面。同时,作者还提醒了读者在使用过程中可能遇到的Android6.0权限问题,并提供了解决方法。 ... [详细]
  • 大数据Hadoop生态(20)MapReduce框架原理OutputFormat的开发笔记
    本文介绍了大数据Hadoop生态(20)MapReduce框架原理OutputFormat的开发笔记,包括outputFormat接口实现类、自定义outputFormat步骤和案例。案例中将包含nty的日志输出到nty.log文件,其他日志输出到other.log文件。同时提供了一些相关网址供参考。 ... [详细]
  • 本文讨论了在shiro java配置中加入Shiro listener后启动失败的问题。作者引入了一系列jar包,并在web.xml中配置了相关内容,但启动后却无法正常运行。文章提供了具体引入的jar包和web.xml的配置内容,并指出可能的错误原因。该问题可能与jar包版本不兼容、web.xml配置错误等有关。 ... [详细]
author-avatar
mobiledu2502910203
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有