前言
HTTP 请求和 Json 解析几乎是当前 APP 开发必备技能了,而 OkHttp 框架又是 Android 开发最常用的网络请求框架之一,因此我基于它进行了二次封装,旨在更高效、快速的完成 APP 应用程序网络请求功能的构建。
问题出在哪
为什么要进行二次封装?了解过 OkHttp 的应该知道,要创建一个 OkHttp 请求的过程有些繁琐,第一你得创建一个 OkHttpClient,额外的你得创建一个请求 Request,其次每次还得做一大堆配置,十分繁琐。
关于 Json,目前最好的两个框架分别是 org.json 和 Gson,两者各有长处,而 org.json 存在的最大的麻烦在于其解析或构建 Json 都需要 捕获异常,而即便是 Gson,对于空数据的情况依然也会束手无策。
基于快速开发以及防后端撕逼原则,对于 Json 解析我们是需要一些宽容度的,即:即便 Json 可能不完整,可能有问题,也不能让我们的 App 崩(bei)溃(guo),基于上述原则,那么我们的封装目的也就很明确了,那就是一方面要将网络请求这事情变简单,另一方面就是让 Json 解析更为容易。
BaseOkHttpV3
这个框架就是对于上述问题解决思路的封装结果了,先上 GitHub 地址:
https://github.com/kongzue/BaseOkHttpV3
先说说创建请求
一般而言,对于的代码编写方式分为一键构建法和流式构建法,而 BaseOkHttpV3 两者都支持,习惯怎么用都可以:
//一键构建法:
HttpRequest.POST(context, "http://www.example.com/femaleNameApi", new Parameter().add("page", "1"), new ResponseListener() {
@Override
public void onResponse(String response, Exception error) {
//返回数据 response
}
});
//流式写法:
HttpRequest.build(context, "http://www.example.com/femaleNameApi")
.addHeaders("Charset", "UTF-8")
.addParameter("page", "1")
.addParameter("token", "A128")
.setResponseListener(new ResponseListener() {
@Override
public void onResponse(String response, Exception error) {
//返回数据 response
}
})
.doPost();
接下来说说请求成功和异常的处理,在 OkHttp 框架中,请求返回结果成功与失败是分别放在不同的方法中执行的,且需要创建 Call 对象才能处理:
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//请求失败
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//请求成功,注意这里还有个坑,response.body().string() 只能获取一次
}
});
但我们经常使用场景中,需要在请求开始时弹出一个 ProgressDialog(加载中提示框)来阻断用户重复请求的行为,而无论请求成功还是失败,这个对话框都需要被关闭(dismiss)那么问题来了,按照 OkHttp 框架原先的写法,你需要在 onFailure 和 onResponse 两个方法中都执行 progressDialog.dismiss(); 代码重复,利用率低。
在上述 BaseOkHttpV3 框架中,仅在同一个 onResponse 方法中返回,开发者只需要做判断即可,error 和 response 同时只会有一个是 null,而 error == null 时即为请求成功,这样无论请求成功与失败都需要执行的代码就可以只写一次了。
通常我们在同一个程序中构建大多数请求都是使用同一个域名地址的子接口地址的,那么能否减轻这块的代码重复量?即,配置全局请求地址。BaseOkHttpV3 框架中也有考虑这种问题,在 BaseOkHttpV3 中提供了大量的全局配置方法,例如全局服务器地址 BaseOkHttp.serviceUrl,配制后所有请求编写时,仅需要写子接口部分的地址即可,框架会自动使用 BaseOkHttp.serviceUrl + 当前创建的请求 url 进行组合发送请求,要临时取消这种组合单独请求别的服务接口地址,仅需要在创建请求时传入“http”开头的请求 url 即可自动不带全局服务器地址发送请求。
诸如此类的全局配置还有很多,例如全局 Header 请求头、全局参数、全局参数拦截器、全局返回拦截器等等,这都是为了方便更多请求场景需要且简化开发成本所做的功能,具体请参考 Github 文档。
最后,BaseOkHttpV3 返回请求结果时,区别于 OkHttp,默认是在主线程返回的,以方便直接对布局进行操作,如需异步线程请手动自行创建。
如何更好的利用 Json
Json 是目前最常用的数据封装方式了,区别于以往的 XML,它更加轻便简洁,其实 org.json 和 Gson 对他的处理已经相当完善了,但我依然觉得有更进一步的空间。
对于 Json 的解析,BaseOkHttpV3 提供了JsonUtil 工具类来完成,JsonUtil 工具类是基于 org.json 库的二次封装,但 JsonUtil 的输出不是 JsonObject 或 JsonArray 对象,而是基于 Map 和 List 的 JsonMap 和 JsonList 对象,且提供了独立的 get 方法,以保证读取到的数据不会出现空指针异常。
JsonMap 和 JsonList 的优势主要在于其解析方便,不需要捕获异常处理,且完全不会空指针。对于异常的 json 文本,例如以下文本:
{
"name":"abc",
"age":"",
"data":null
}
其中的 age 预期是 int 类型,如果使用 org.json 和 Gson 库,都可能遇到麻烦,但对于 BaseOkHttpV3 来说是毫无问题的,使用 getInt("age") 获取到的值会是 0,如果你想做判断,可以设置默认值为 -1,使用代码 getInt("age", -1) 即可,在 BaseOkHttpV3 的 Json 解析框架中,所有获取到的值,无论 getString(key)、getInt(key)、getBoolean(key)还是其他类型,甚至对于上述使用 Json使用 getJsonMap("data").getString("message"); 的代码,都不会出现空指针,可以尽管放心大胆的解析。
如此设计的主要目的是为了方便解决对于可能出现的后端给出数据存在异常的情况下,保证 App 不崩溃,且能够高效构建代码。在 BaseOkHttpV3 的 Json 解析库中,你甚至可以忽略类型,对于 boolean 的值可以直接解析成 string,对于 string 的值你也可以直接解析成 int,都不会出现 App 的问题,尽管这确实有些不严谨,但却能大大提升开发的效率,缩短开发周期,减少不必要的麻烦。
另外, JsonMap 和 JsonList 对象是 Map 和 List 的子类,也就是说,对于一段 Json 集合,可以直接通过 JsonUtil 解析成 JsonList 参与 ListView、RecycleView 等组件的适配器 Adapter 构建,快速完成从网络请求数据到界面呈现的转换,省去构造 JavaBean 的繁琐步骤。
防撕逼?我看行
BaseOkHttpV3 还有一个非常亮点的设计,那就是日志打印,这个设计也主要是为了防止出现责任不明的问题,对于 BaseOkHttpV3 的请求,在开启日志打印开关后 BaseOkHttp.DEBUGMODE = true; 你可以在控制台看到非常完整规范的日志结果:

对于 Json 文本会自动进行格式化,且针对每一个接口的发送、返回、错误都有明确的显示,我相信这对于日常开发查错来说也会是极佳的助力。
总结
BaseOkHttpV3 的封装主要是为了解决开发过程中遇到的很多痛点和难点,本文着重讲述了 BaseOkHttpV3 的封装目的以及对于一般请求以及 Json 解析的良好支持,除此之外,BaseOkHttpV3 也对 PUT、GET、DELETE 请求、HTTPS、WebSocket 以及 Cookie 做了封装,有兴趣可以移驾 Github 详细查看:https://github.com/kongzue/BaseOkHttpV3
如有任何疑问可以在 Github 提出您的 issues,也可以加入大话安卓讨论群: 271127803 与我讨论。写文章不易,如果觉得好还劳烦点个赞吧!
网友评论