序言

OkHttp 的强大算是毋庸置疑了;OkHttp 基本在网络层能完成任何事情,适用任何情况;正因为如此 OkHttp 每次构建一个请求的时候不得不写大量的代码来完成相应的配置。在这里分享一个极限封装OkHttp的辅助框架,通过该框架能最大程度简化你的开发负担。好话不多说,往下看看就知道好不好。

原生

在这里举例几个原生情况下使用 okhttp 的情况。

GET

    public void get() {Request.Builder builder = new Request.Builder().url("http://www.xx.com?id=dd&aa=sdd").get();Request request = builder.build();Call call = new OkHttpClient().newCall(request);// 同步try {call.execute();} catch (IOException e) {e.printStackTrace();}// 异步call.enqueue(new Callback() {@Overridepublic void onFailure(Request request, IOException e) {}@Overridepublic void onResponse(Response response) throws IOException {}});}

Form

    public void form() {FormEncodingBuilder formEncodingBuilder = new FormEncodingBuilder();// Add valuesformEncodingBuilder.add("id", "dd");formEncodingBuilder.add("name", "sdd");RequestBody body = formEncodingBuilder.build();Request request = new Request.Builder().post(body).build();// do call...}

文件

    public void file() {MultipartBuilder builder = new MultipartBuilder();builder.type(MultipartBuilder.FORM);builder.addFormDataPart("id", "dd");builder.addFormDataPart("name", "sdd");RequestBody fileBody = RequestBody.create(MediaType.parse("image/png"), new File("aa.png"));builder.addFormDataPart("head", "aa.png", fileBody);RequestBody body = builder.build();Request request = new Request.Builder().post(body).build();// do call...}

不得不说,okhttp算是封装的非常Nice的框架,就算是文件发送也只是简单的几行代码就OK了。
不过假如我们需要在返回时进行UI切换,或者返回的数据进行对应的JSON解析呢?
也很简单就是得到数据后然后来一个线程切换,然后再使用GSON解析一下就好。

但是我们是否还可以简化呢?因为每次请求都需要构建build-request-发送-解析,这些操作很少,但是没必要没错重复。

初衷

之所以再次封装,就是为了让每次的build过程不再出现,当然功能肯定不能仅仅局限于此。
假如你现在登录后得到一个ID,要求后续操作都带上ID进行操作你会怎么办?
难道每次请求参数中都加上一次?这就是一个值得封装的地方。

封装只是为了能更加简单,仅此而已~

功能

  • UI 线程切换
  • 可选择的Callback(任意选择UI线程或者子线程)
  • 参数规范化,GET与POST都一样的传参方式
  • 上传/下载进度回调
  • 可以简单的设置Head部分
  • 可以每次请求时自动加上需要的参数
  • String/JSON/byte/File… 都能一样简单

用法

由于辅助代码较多,在这里就不一一贴出来了,在这里仅仅演示如何使用。

异步GET

        Http.getAsync("http://wthrcdn.etouch.cn/weather_mini", new UiCallback<String>() {@Overridepublic void onFailure(Request request, Response response, Exception e) {log("getAsync:onFailed");}@Overridepublic void onSuccess(String response, int code) {log("getAsync:onSuccess:" + response);}}, new StrParam("citykey", 101010100)
);

由于是 get 请求,在这里参数中的 citykey 会被自动解析到 url 中。

http://wthrcdn.etouch.cn/weather_mini?citykey=101010100

同步GET

final String url = "http://wthrcdn.etouch.cn/weather_mini?citykey=101010100";
String str = Http.getSync(String.class, url);
log("getSync1:" + str);str = Http.getSync(url, new ThreadCallback<String>() {@Overridepublic void onFailure(Request request, Response response, Exception e) {log("getSync2:onFailed");}@Overridepublic void onSuccess(String response, int code) {log("getSync2:onSuccess:" + response);}
});
log("getSync2:" + str);

同步方式支持两种情况,一种有Callback,一种是没有。

当然就算加上了Callback也并不是异步,此时方法会等到执行完成后才会继续往下走。之所以这么干,是为了方便在callback中直接处理ui的事儿。

在这里有必要说明一下,返回类型需要进行指定,如果没有Callback哪么需要你传入返回类型class。

当然如果你传入了callback,哪么此时class就由callback

Account account = Http.getSync(Account.class, url);
User user = Http.getSync(User.class, url);
String str = Http.getSync(String.class, url, new StrParam("citykey", 101010100));

Callback 的情况也如上所示。

异步与同步的区别在于方法名称:

  • Http.getSync()
  • Http.getAsync()
  • Http.postSync()
  • Http.postAsync()
  • Http.uploadSync()
  • Http.uploadAsync()
  • Http.downloadSync()
  • Http.downloadAsync()

默认情况下,upload与download具有callProgress 回调进度功能。

POST

        String value1 = "xxx";String value2 = "xxx";String url = "http://www.baidu.com";Http.postAsync(url, new HttpCallback<String>() {@Overridepublic void onFailure(Request request, Response response, Exception e) {e.printStackTrace();}@Overridepublic void onSuccess(String response, int code) {log(response);}},new StrParam("value1", value1),new StrParam("value2", value2));

post 的请求方法与get基本如出一辙。

Upload

File file = getAssetsFile();
Http.uploadAsync("http://img.hoop8.com/upload.php", "uploadimg", file, new UiCallback<String>() {@Overridepublic void onProgress(long current, long count) {super.onProgress(current, count);log("uploadAsync onProgress:" + current + "/" + count);mUpload.setProgress((int) ((current * 100.00 / count)));}@Overridepublic void onFailure(Request request, Response response, Exception e) {e.printStackTrace();log("uploadAsync onFailed");}@Overridepublic void onSuccess(String response, int code) {log("uploadAsync onSuccess:" + response);}
});

上传部分也很简单,如果需要带有参数哪么和Post的使用方式一样。当然此时传入参数就不是 StrParam 而是 IOParam.

上传的时候你可以仅仅传递文件+文件对应的name;或者 传递 IOParam; 也可以 StrParam+IOParam的方式;当然终极一点你可以传递:Param 类型。

Param 类型是 StrParam 与 IOParam 的结合体。

哪么上传你也可以这样:

Http.uploadAsync("url", callback, new IOParam("uploadimg", file));
Http.uploadAsync("url", callback,new StrParam[]{new StrParam("id", 123456), new StrParam("name", "qiujuer")},new IOParam("uploadimg", file));Http.uploadAsync("url", callback,new Param("id", 123456),new Param("name", "qiujuer"),new Param("uploadimg", file));

Download

Http.downloadAsync("https://raw.githubusercontent.com/qiujuer/OkHttpPacker/master/release/sample.apk", getSDPath(), null, null, new UiCallback<File>() {
@Override
public void onProgress(long current, long count) {super.onProgress(current, count);log("downloadAsync onProgress:" + current + "/" + count);mDownload.setProgress((int) ((current * 100.00 / count)));
}@Override
public void onFailure(Request request, Response response, Exception e) {e.printStackTrace();log("downloadAsync onFailed");
}@Override
public void onSuccess(File response, int code) {log("downloadAsync onSuccess:" + response.getAbsolutePath());
}
});

下载这里为了方便所以强制返回File,哪么你拿到的时候就是下载好的文件了。
下载只有异步方式,也同样支持传入参数。
而在传入参数上,你可以仅仅传递一个存储目录,此时文件名会根据url进行指定。
当然你还可以传递目录+文件名。
也或者你直接传入一个文件(File)。

其中的Object是用于传入时设置Tag,方便OKHTTP进行cancel()取消。

参数

在所有方式中 Post 支持参数最多,所以这里就使用 Post 进行演示。

// 无参数情况
Http.postAsync("url", callback);// StrParam
Http.postAsync("url", callback, new StrParam("id", 113321));// List
List<StrParam> strParamList = new ArrayList<>();
strParamList.add(new StrParam("id", 113321));
Http.postAsync("url", callback, strParamList);// Map
Map<String, String> strParamMap = new HashMap<>();
strParamMap.put("id", "113321");
Http.postAsync("url", callback, strParamMap);// String
Http.postAsync("url", callback, "This is post body.");// Byte
Http.postAsync("url", callback, new byte[]{1, 2});// File
Http.postAsync("url", callback, new File("img.png"));// JSON
JSONObject jsonObject = new JSONObject("json data");
Http.postAsync("url", callback, jsonObject);// JSONArray
JSONArray jsonArray = new JSONArray();
Http.postAsync("url", callback, jsonArray);

请求构建

在本框架中,所有的请求都会把url与参数经过请求构建器进行请求体构建。所以如果你需要为你的每一个请求都带上特定的参数是非常简单的。

第一种方式:

RequestBuilder builder = Http.getInstance().getRequestBuilder();
((RequestCallBuilder) builder).setBuilderListener(new RequestCallBuilder.BuilderListener() {// 请求头构建,在这里你可以做一些请求头的初始化操作@Overridepublic void onCreateBuilder(Request.Builder builder) {builder.addHeader("User-Agent", "User-Agent");builder.addHeader("Head-Content", "Head-Content");}// 构建Get时调用@Overridepublic boolean onBuildGetParams(StringBuilder sb, boolean isFirst) {// isFirst 用于告知是否是第一个参数// 因为GET请求第一个参数是加上 "?" ,而其后参数则是加上 "&"// 返回时也用于告知当前参数中是否已经有参数了,// 如果已经有了哪么返回 false ,没有加上任何参数 返回 true// 或许把名称改成 haveParam 要恰当一点if (isFirst) {isFirst = false;sb.append("?");} else {sb.append("&");}sb.append("uid=");sb.append("qiujuer");return isFirst;}// 构建 Form body 时调用@Overridepublic void onBuildFormBody(FormEncodingBuilder formEncodingBuilder) {formEncodingBuilder.add("uid", "qiujuer");}// 构建 Multipart body 时调用@Overridepublic void onBuildMultipartBody(MultipartBuilder multipartBuilder) {multipartBuilder.addFormDataPart("uid", "qiujuer");}
});

第二种

import com.squareup.okhttp.FormEncodingBuilder;
import com.squareup.okhttp.MultipartBuilder;
import com.squareup.okhttp.Request;import net.qiujuer.common.okhttp.impl.RequestCallBuilder;/*** Created by qiujuer* on 16/1/13.*/
public class MyRequestBuilder extends RequestCallBuilder {@Overrideprotected boolean buildGetParams(StringBuilder sb, boolean isFirst) {if (isFirst) {isFirst = false;sb.append("?");} else {sb.append("&");}sb.append("uid=");sb.append("qiujuer");return isFirst && super.buildGetParams(sb, isFirst);}@Overrideprotected FormEncodingBuilder buildFormBody(FormEncodingBuilder formEncodingBuilder) {formEncodingBuilder.add("uid", "qiujuer");return super.buildFormBody(formEncodingBuilder);}@Overrideprotected MultipartBuilder buildMultipartBody(MultipartBuilder multipartBuilder) {multipartBuilder.addFormDataPart("uid", "qiujuer");return super.buildMultipartBody(multipartBuilder);}@Overrideprotected Request.Builder createBuilder() {Request.Builder builder = super.createBuilder();builder.addHeader("User-Agent", "User-Agent");builder.addHeader("Head-Content", "Head-Content");return builder;}
}
Http.getInstance().setRequestBuilder(new MyRequestBuilder());

两种办法都是OK的,不过建议第一种,方便快捷。以后可以在第一种的方式上再封装一次,封装到 Param 层次那就简单了。

解析器

在本框架中,所有的返回都会经过解析器对返回数据进行解析;这也就达到了直接把 JSON 数据解析为 Class 的目的。

默认情况下采用GSON进行解析。你也可以重写解析器。

GSON配置

有时候返回的数据样式并不是 Gson 的默认样式(一般是时间字符串),此时会导致解析失败,这里提供一种简单的办法。

GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setDateFormat("yyyy-MM-dd HH:mm:ss");
Gson gson = gsonBuilder.create();Http.getInstance().setResolver(new GsonResolver(gson));

FastJson

如果你不想使用 Gson进行解析,或许你会采用FastJson,哪么你可以重写实现解析器。

import net.qiujuer.common.okhttp.core.Resolver;import java.lang.reflect.Type;/*** Created by qiujuer* on 16/1/13.*/
public class MyResolver implements Resolver {@Overridepublic Object analysis(String rsp, Type type) {return null;}@Overridepublic Object analysis(String rsp, Class<?> subclass) {return null;}
}

解析方法有两种,两个方法你都需要自己去完善。
rsp 是网络返回的字符串。
Type 是等待返回的 ClassType

Cookie

关于 Cookie 支持,默认情况下 Cookie 存储是处于关闭状态,如果你想要存储网址Cookie到本地文件,并每次访问时都使用当前Cookie。

// 允许存储Cookie
Http.enableSaveCookie(getApplication());
// 清理Cookie
Http.removeCookie();
// 得到所有Cookie
Http.getCookie();

OkHttpClient

有时你需要拿到当前的 Client ,比如你可以把 Client 设置为 Glide 的网络驱动器。

OkHttpClient client = Http.getClient();
// Glide
Glide.get(application).register(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(client));

调试

如果你需要知道每次请求Url与参数信息,你可以打开LOG开关。

Http.DEBUG = true;

关于 HTTPS

在当前框架中并没有直接集成 HTTPS 的支持,而是采用了一个 CertTool 证书 工具来进行 HTTPS 支持。

通过 CertTool 你可以方便的设置一个本地证书文件进行 HTTPS 请求。

CertTool.setCertificates(Http.getClient(),new FileInputStream(new File()));

Callback

HttpCallback

该Callback为默认需要,其中:

  • onStart UI 线程中执行
  • onFinish UI 线程中执行
  • onProgress, onFailure, onSuccess 子线程中执行

ThreadCallback

所有回调全部在子线程中执行。

UICallback

所有回调在UI线程中执行。

项目地址

https://github.com/qiujuer/OkHttpPacker

如果使用上有任何问题欢迎提交 issues 。

========================================================
作者:qiujuer
博客:blog.csdn.net/qiujuer
网站:www.qiujuer.net
开源库:github.com/qiujuer/Genius-Android
开源库:github.com/qiujuer/Blink
转载请注明出处:http://blog.csdn.net/qiujuer/article/details/50442600
—— 学之开源,用于开源;初学者的心态,与君共勉!

========================================================

[Android]OkHttp的简单封装-辅助框架相关推荐

  1. Android OkHttp + Glide + RecyclerView + ButterKnife流行框架的综合实现

    文章目录 要求 运行效果 任务描述 框架地址 分析 代码实现 Movie INetCallBack MovieOkHttpUtils MovieRecyclerViewAdapter MovieBiz ...

  2. Android APP更新下载工具类——简单封装DownloadManager

    几乎所有APP都包含了检查更新功能,更新下载功能的实现方式常用的有两种:1.使用App网络框架的文件下载请求:2.使用自带的DownloadManager类:本文介绍第二种,简单封装一下Downloa ...

  3. Android OkHttp框架解析

    Okhttp是由Sqare公司开发的开源网络访问库,是目前比较火的网络框架, 它处理了很多网络疑难杂症:会从很多常用的连接问题中自动恢复.如果你的服务器配置了多个IP地址,当第一个IP连接失败的时候, ...

  4. Android客户端连接服务器- OKHttp的简单实用方法

    文章目录 一 .OKHttp简介 二. OkHttp3使用 1.创建HTTPClient实例 2.Get请求 3.POST请求 三.Timeouts(超时) **写在前面:本文只是对OKHttp3的简 ...

  5. Android OkHttp+Retrofit+Rxjava+Hilt 的网络请求封装

    今天给大家简单的封装一个现在比较流行的网络请求框架 第一步是导入我们所需要的依赖还需要在android {}闭包下添加一个 buildFeatures{viewBinding true } imple ...

  6. Android之全面解析Retrofit网络框架封装库

    转载请标明出处:[顾林海的博客] 前言 Retrofit是Square公司推出的一个HTTP的框架,主要用于Android和Java,Retrofit会将每一个HTTP的API请求变成一个Java的接 ...

  7. 【OkHttp】OkHttp 源码分析 ( 网络框架封装 | OkHttp 4 迁移 | OkHttp 建造者模式 )

    OkHttp 系列文章目录 [OkHttp]OkHttp 简介 ( OkHttp 框架特性 | Http 版本简介 ) [OkHttp]Android 项目导入 OkHttp ( 配置依赖 | 配置 ...

  8. Android AsyncTask 深度理解、简单封装、任务队列分析、自定义线程池

    前言:由于最近在做SDK的功能,需要设计线程池.看了很多资料不知道从何开始着手,突然发现了AsyncTask有对线程池的封装,so,就拿它开刀,本文将从AsyncTask的基本用法,到简单的封装,再到 ...

  9. Spring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发

    Spring JDBC     * Spring框架对JDBC的简单封装.提供了一个JDBCTemplate对象简化JDBC的开发     * 步骤:         1. 导入jar包        ...

  10. Android地址(省市区)、日期、时间滚轮选择器简单封装

    前言: 1.android开发中时间.日期.地址等滚轮选择器很常见,很多App会使用这种效果,收集了一下资料,于是自己做了一个简单封装,方便使用,感谢各位大佬的资料,效果如图: 2.使用方法代码如下: ...

最新文章

  1. grep 在HP-UX下的递归查找
  2. php 批量导出excel文件,PHPEXCEL批量导出
  3. Java中switch对整型/字符型/字符串型具体实现细节
  4. 《互联网思维》读后感与笔记
  5. 文件夹和文件的名称变成蓝色
  6. 如何设计一个 A/B test?
  7. word2vec应用场景_word2vec的使用参数解释和应用场景
  8. Qt C++ 命名空间namespaces讲解
  9. 使用日志审计查看MaxCompute执行过哪些操作
  10. 网站压力测试工具 webbench
  11. Windows网络编程之Socket高级编程简介
  12. 你有被代理过吗?讲讲开源框架都在用的代理模式
  13. 3GPP最新提案查询方法
  14. 大型复杂项目集管理之二——项目集治理
  15. English Reading - Thai cave rescue boys relive 'moment of miracle'
  16. java openni rgb显示_3D将深度映射到RGB(Kinect OpenNI Depthmap到OpenCV RGB Cam)
  17. 1-Scrapy Tutorial
  18. 【敏捷】1.0 待办事项列表
  19. windows驱动ddk环境设置
  20. 商务签证的准备(1)

热门文章

  1. Hbase API实现倒序查询
  2. .NET core ABP 获取远程IP地址
  3. Android MediaPlayer播放raw资源封装类
  4. 实现Ajax异步的layui分页
  5. 设计模式 单例模式 使用模板及智能指针
  6. 新建samba配置步骤
  7. 不常用,但热门的IOS第三方库(转)
  8. ubuntu 12.04 修改 grub 启动参数
  9. Redis主从,哨兵架构简单搭建
  10. luncence学习