您的位置:首页 > 理论基础 > 计算机网络

Okhttp3网络请求框架简析思考——Android网络请求框架(五)

2016-09-13 00:00 666 查看
摘要: 1、单例设计模式封装工具类
2、对网络请求设置缓存
3、对网络请求设置超时间
4、get请求
5、Post请求
6、post提交表单数据请求
7、post提交JSON数据请求

站在世界的巅峰看世界的心情,决不是一个普通人能够体会的到的感觉

1、对单例设计模式的思考

创建方式一 、

/**
* Created by androidlongs on 16/9/12.
* 站在顶峰,看世界
* 落在谷底,思人生
*/

/**
* 创建方式一:
*
* 当在JVM在加载单例类的时候,单例对象就会被建立
* 当其中有其他的静态方法的时候,使用类调用方法,没有使用到该单例对象,但是单例对象也会被创建出来,从而造成了资源的浪费
*/
public class Singleton {
//直接创建
public static  Singleton sSingleton = new Singleton();
//私有构造函数
private Singleton(){

}
//返回对象体
public static Singleton getInstance(){
return sSingleton;
}
//获取String的方法
public static String getString(){
return "single";
}

}


创建方式 二

/**
* Created by androidlongs on 16/9/12.
* 站在顶峰,看世界
* 落在谷底,思人生
*/

/**
* 创建方式二
*
* 有点性能上的损失
*/
class SingletonLazy{
//声明变量
public static  SingletonLazy sSingletonLazy;
//私有构造函数
private SingletonLazy(){

}
//提供对外方法
public static  SingletonLazy getInstance(){
if (sSingletonLazy == null) {
synchronized (SingletonLazy.class){
if (sSingletonLazy == null) {
sSingletonLazy = new SingletonLazy();
}
}
}
return sSingletonLazy;
}

//获取String的方法
public static  String getString(){
return "single";
}

}


创建方式三:

/**
* 创建方式三
*/
class  CommonSingleton{
//私有构造
private CommonSingleton(){

}
//提供对外方法
public static CommonSingleton getInstance(){
return  SingletonHolder.commonSingleton;
}
//内部类方法维护
private static class SingletonHolder{
private static CommonSingleton commonSingleton = new CommonSingleton();
}
//获取String的方法
public static String getString(){
return "single";
}

}

分析 简述:

1-1、可以看到上面三种创建单例的方法,第一种方式被传统命名为饿汉式,单例对象随着类的加载而被创建,当我们使用类中的其他静态方法而没有使用到单例对象的时候,单例对象依然会被创建出来,从某种角度来说,造成了一定的内存浪费。

1-2、第二种方式被传统命名为懒汉式,也就是在调用实例化对象的时候,才会将单例对象创建出来,当我们使用类中的其他静态方法的时候,会同时有单例对象的null引用生成,在一定程度上会很消耗内存,再者创建实例化对象的时候,双重非空锁判断,也是相当消耗性能的工作。

1-3、第三种方式可以称为是完美设计版了,因为它可以解决前两种设计方法的不足之处,当去调用类的实例化方法的时候,单例对象才会被创建,而当调用类中的其他静态方法的时候,对静态单例对象没有任何的操作,所以可以说是比较完美的了,之所以可以称为比较而不是完全,是因使用这种方式创建,在进行序列化与反序列化的时候,会出现非单例对象问题。

2、使用单例设计模式来创建Okhttp网络请求框架

/**
* Created by androidlongs on 16/9/12.
* 站在顶峰,看世界
* 落在谷底,思人生
*/
public class CommonOkhttpUtils {
//私有化构造
private CommonOkhttpUtils(){
//初始化Okhttp配制
initOkHttpFunction();
}

//提供实例化对象
public static CommonOkhttpUtils getUtilsInstance(){
return  OkHttpSingle.sCommonOkhttpUtils;
}
//实例静态内部类
private static class OkHttpSingle{
private static CommonOkhttpUtils sCommonOkhttpUtils = new CommonOkhttpUtils();
}

//初始化Okhttp配制
private void initOkHttpFunction() {

}
}

当然在使用Okhttp3的时候 要先关联依赖

compile 'com.squareup.okhttp3:okhttp:3.3.1'


3、对Okhttp3进行的一些初始化配制

private OkHttpClient mOkHttpClient;
//初始化Okhttp配制
private void initOkHttpFunction() {
//配制网络数据缓存
File cacheDirectory = APPApplication.getmContext().getExternalCacheDir();
//配制网络数据缓存大小  10M
int cacheSize = 10*1024*1024;
//
Cache cache = new Cache(cacheDirectory,cacheSize);
//创建HttpClientBuilder
OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
//设置缓存 以及超时间 以及获取OkHttpClient对象
mOkHttpClient = builder.writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.cache(cache)
.build();
}


4、网络请求思路综述

其实创建一个网络连接并没有多复杂

4-1 创建请求Request对象

4-2创建封装参数的RequestBody对象(GET方法除外)

4-3 封装请求参数

4-4 创建请求Response对象实例

4-5 发起网络请求

4-6 处理回调监听

4-7 处理取消网络请求标签

5、GET异步请求(可传参数 )

/**
* 异步GET网络请求
*
* @param url          请求网络链接
* @param headerMap    请求网络添加头信息
* @param paramsMap    请求网络参数
* @param cacheControl 缓存模式
*
*                     public static final CacheControl FORCE_NETWORK = ..;
*
*                     public static final CacheControl FORCE_CACHE = ...
* @param callback     响应回调
* @param tag          网络任务标识
*/
public void okHttpGetRequest(String url, Map<String, String> headerMap, Map<String, String> paramsMap, CacheControl cacheControl, Callback callback, String tag) {

//GET请求-1 封装请求参数
//Get请求传参数实际上是在请求链接中携带参数
StringBuilder sb = new StringBuilder();
sb.append(url).append("?");

if (paramsMap != null && !paramsMap.isEmpty()) {
for (String key : paramsMap.keySet()) {
sb.append(key).append("=").append(paramsMap.get(key)).append("&");
}
sb = sb.deleteCharAt(sb.length() - 1);
url = sb.toString();
}

//GET请求-2 获取Builder
Request.Builder builder = new Request.Builder().url(url);

//GET请求-3 设置缓存
if (cacheControl != null) {
builder.cacheControl(cacheControl);
}
//GET请求-4添加请求头信息
if (headerMap != null && !headerMap.isEmpty()) {
for (Map.Entry<String, String> entry : headerMap.entrySet()) {
builder.addHeader(entry.getKey(), entry.getValue());
}
}
//GET请求-5 创建请求Request对象
Request request = builder.build();
//GET请求-6 设置取消标签
Call call = mOkHttpClient.newCall(request);
//将请求标签添加到请求Key集合中
mCallHashMap.put(tag, call);
//GET请求-5 发起网络请求
call.enqueue(callback);
}

/**
* 移除 取消网络任务
*
* @param tag
*/
public void removeRequest(String tag) {
//获取KEY的集合
Set<Map.Entry<String, Call>> keyEntries = mCallHashMap.entrySet();
//如果包含KEY
if (keyEntries.contains(tag)) {
//获取对应的Call
Call call = mCallHashMap.get(tag);
//如果没有被取消 执行取消的方法
if (!call.isCanceled()) {
call.cancel();
}
//移除对应的KEY
mCallHashMap.remove(tag);
}
}

这是GET请求参数最多的方法,我们可以在此基础上封装少参数的方法,例如不需要设置请求头,请求参数,不指定缓存模式,对应的传入null就可以。这里实际上就是将传入的参数以KEY - VALUE的方式拼接在了请求链接中

对于网络请求模式,默认有两种,一是强制使用网络请求数据 ,一是强制使用缓存,一般使用默认使用网络请求就可以

使用案例 :

//GET访问
private void getRequestFunction() {
//请求链接
String url = "";
//网络请求标识
String tag = "getRequest";

//提交参数
Map<String, String> paramMap = new HashMap<>();
paramMap.put("userName", "xxx");
paramMap.put("password", "123456");

//添加请求Header
Map<String, String> heardMap = new HashMap<>();
heardMap.put("verson", "11");

CommonOkhttpUtils.getUtilsInstance().okHttpGetRequest(url, heardMap, paramMap, CacheControl.FORCE_NETWORK, new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//请求失败回调方法
}

@Override
public void onResponse(Call call, Response response) throws IOException {
//请求成功回调方法
}
}, tag);
}

//取消网络请求
private void canlaneRequest(String tag){
CommonOkhttpUtils.getUtilsInstance().removeRequest(tag);
}

通过抓包可以看到我们提交的请求数据为



6、POST异步请求提交表单数据

/**
* 异步POST网络请求  提交表单数据
*
* @param url          请求网络链接
* @param headerMap    请求网络添加头信息
* @param parmMap    请求网络参数
* @param cacheControl 缓存模式
*                     public static final CacheControl FORCE_NETWORK = ..;
*
*                     public static final CacheControl FORCE_CACHE = ...
* @param callback     响应回调
* @param tag          网络任务标识
*/
public void okPostFormRequest(String url, Map<String, String> headerMap, Map<String, String> parmMap, CacheControl cacheControl, Callback callback, String tag) {
//POST - FORM 表单 获取请求参数BODY
FormBody.Builder formBuilder = new FormBody.Builder();

//POST - FORM 表单 封装参数
if (parmMap != null && !parmMap.isEmpty()) {
for (Map.Entry<String, String> entry : parmMap.entrySet()) {
formBuilder.add(entry.getKey(), entry.getValue());
}
}

//POST - FORM 获取表单BODY
RequestBody formBody = formBuilder.build();
//POST - FORM 构建请求Request Builder
Request.Builder requestBuilder = new Request.Builder().url(url);

//POST - FORM 设置缓存

if (cacheControl != null) {
requestBuilder.cacheControl(cacheControl);
}

//POST - FORM 添加请求头信息
if (headerMap != null && !headerMap.isEmpty()) {
for (Map.Entry<String, String> entry :
headerMap.entrySet()) {
requestBuilder.addHeader(entry.getKey(), entry.getValue());
}
}
//POST - FORM 构建请求Request
Request request = requestBuilder.post(formBody).build();
//POST - FORM 构建请求响应Call
Call call = mOkHttpClient.newCall(request);
//POST - FORM 设置取消任务标签
mCallHashMap.put(tag,call);
//POST - FORM 发起请求
call.enqueue(callback);
}

/**
* 移除 取消网络任务
*
* @param tag
*/
public void removeRequest(String tag) {
//获取KEY的集合
Set<Map.Entry<String, Call>> keyEntries = mCallHashMap.entrySet();
//如果包含KEY
if (keyEntries.contains(tag)) {
//获取对应的Call
Call call = mCallHashMap.get(tag);
//如果没有被取消 执行取消的方法
if (!call.isCanceled()) {
call.cancel();
}
//移除对应的KEY
mCallHashMap.remove(tag);
}
}
}

案例:

private void postRequestForm() {
//请求链接
String url = "http://192.168.1.107:8080/OkhttpAppLication/test";
//网络请求标识
String tag = "getRequest";

//提交参数
Map<String, String> paramMap = new HashMap<>();
paramMap.put("userName", "xxx");
paramMap.put("password", "123456");

//添加请求Header
Map<String, String> heardMap = new HashMap<>();
heardMap.put("verson", "11");
CommonOkhttpUtils.getUtilsInstance().okPostFormRequest(url, heardMap, paramMap, CacheControl.FORCE_NETWORK, new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//请求失败回调方法
}

@Override
public void onResponse(Call call, Response response) throws IOException {
//请求成功回调方法
}
}, tag);
}

通过抓包工具可以看到提交的数据为:

提交数据的格式为: Content - Type:application/x-www-form-urlencoded

添加的请求头为 verson : 11



提交的参数为:



7、POST异步请求提交JSON数据

/**
* 异步POST网络请求 提交JSON数据
*
* @param url          请求网络链接
* @param headerMap    请求网络添加头信息
* @param parmMap    请求网络参数
* @param cacheControl 缓存模式
*                     public static final CacheControl FORCE_NETWORK = ..;
*
*                     public static final CacheControl FORCE_CACHE = ...
* @param callback     响应回调
* @param tag          网络任务标识
*/
public void okPostJSONRequest(String url, Map<String, String> headerMap, Map<String, String> parmMap, CacheControl cacheControl, Callback callback, String tag) {
//获取Builder
Request.Builder builder = new Request.Builder().url(url);
// 设置缓存
if (cacheControl != null) {
builder.cacheControl(cacheControl);
}

//添加请求头信息
if (headerMap != null && !headerMap.isEmpty()) {
for (Map.Entry<String, String> entry : headerMap.entrySet()) {
builder.addHeader(entry.getKey(), entry.getValue());
}
}
/**
* 封装参数
*/
JSONObject jsonObject = new JSONObject();
if (parmMap != null && !parmMap.isEmpty()) {
for (Map.Entry<String, String> entry :parmMap.entrySet()) {
try {
jsonObject.put(entry.getKey(), entry.getValue());
} catch (JSONException e) {
e.printStackTrace();
}
}
}

//获取RequestBody
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"),jsonObject.toString());
//获取 Request
Request request = builder.post(requestBody).build();
//获取Call
Call call = mOkHttpClient.newCall(request);
//POST - JSON 设置取消任务标签
mCallHashMap.put(tag,call);
//POST - JSON 发起请求
call.enqueue(callback);
}
/**
* 移除 取消网络任务
*
* @param tag
*/
public void removeRequest(String tag) {
//获取KEY的集合
Set<Map.Entry<String, Call>> keyEntries = mCallHashMap.entrySet();
//如果包含KEY
if (keyEntries.contains(tag)) {
//获取对应的Call
Call call = mCallHashMap.get(tag);
//如果没有被取消 执行取消的方法
if (!call.isCanceled()) {
call.cancel();
}
//移除对应的KEY
mCallHashMap.remove(tag);
}
}

在这里,我们将参数以map集合形式传入,然后封装成JSONObject对象,然后在构造请求体,

例 :

private void postJsonFunction() {
//请求链接
String url = "http://192.168.1.107:8080/OkhttpAppLication/test";
//网络请求标识
String tag = "getRequest";

//提交参数
Map<String, String> paramMap = new HashMap<>();
paramMap.put("userName", "xxx");
paramMap.put("password", "123456");
paramMap.put("sex", "man");

//添加请求Header
Map<String, String> heardMap = new HashMap<>();
heardMap.put("verson", "11");
CommonOkhttpUtils.getUtilsInstance().okPostJSONRequest(url, heardMap, paramMap, CacheControl.FORCE_NETWORK, new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//请求失败回调方法
}

@Override
public void onResponse(Call call, Response response) throws IOException {
//请求成功回调方法
}
}, tag);
}

通过抓包工具可以看到提交的请求数据为:



请求方式为:



8、POST异步请求提交JSON数据

/**
* 异步POST网络请求 提交JSON数据
*
* @param url          请求网络链接
* @param headerMap    请求网络添加头信息
* @param JSONBody     请求网络JSON字符串
* @param cacheControl 缓存模式
*
*                     public static final CacheControl FORCE_NETWORK = ..;
*
*                     public static final CacheControl FORCE_CACHE = ...
* @param callback     响应回调
* @param tag          网络任务标识
*/
public void okPostJSONRequest(String url, Map<String, String> headerMap, String JSONBody, CacheControl cacheControl, Callback callback, String tag) {
//获取Builder
Request.Builder builder = new Request.Builder().url(url);
// 设置缓存
if (cacheControl != null) {
builder.cacheControl(cacheControl);
}

//添加请求头信息
if (headerMap != null && !headerMap.isEmpty()) {
for (Map.Entry<String, String> entry : headerMap.entrySet()) {
builder.addHeader(entry.getKey(), entry.getValue());
}
}
//获取RequestBody
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), JSONBody);
//获取 Request
Request request = builder.post(requestBody).build();
//获取Call
Call call = mOkHttpClient.newCall(request);
//POST - JSON 设置取消任务标签
mCallHashMap.put(tag, call);
//POST - JSON 发起请求
call.enqueue(callback);
}

在这里,我们将直接构造好的JSON 字符串直接传入到方法中,然后构造请求体

案例:

private void postJsonFunction1() {
//请求链接
String url = "http://192.168.1.107:8080/OkhttpAppLication/test";
//网络请求标识
String tag = "getRequest";

//提交参数
String JSONString = "";

JSONObject jsonObj = new JSONObject();
JSONArray jsonArray = new JSONArray();
try {
for (int i = 0; i < 4; i++) {
JSONObject jsono = new JSONObject();
jsono.put("userName", "xxx" + i);
jsono.put("password", "123456" + i);
jsonArray.put(jsono);
}
jsonObj.put("date", jsonArray);
jsonObj.put("sex", "man");
}catch (Exception e){

}
JSONString = jsonObj.toString();

//添加请求Header
Map<String, String> heardMap = new HashMap<>();
heardMap.put("verson", "11");
CommonOkhttpUtils.getUtilsInstance().okPostJSONRequest(url, heardMap,JSONString, CacheControl.FORCE_NETWORK, new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//请求失败回调方法
}

@Override
public void onResponse(Call call, Response response) throws IOException {
//请求成功回调方法
}
}, tag);
}

提交的请求数据为:

{
"date":
[{
"userName": "xxx0",
"password": "1234560"
}, {
"userName": "xxx1",
"password": "1234561"
}, {
"userName": "xxx2",
"password": "1234562"
}, {
"userName": "xxx3",
"password": "1234563"
}],
"sex": "man"
}

也就是说在这里我们可以定义任意结构层次的JSON数据

9、POST异步请求提交String 数据

/**
* 异步POST网络请求 提交String数据
*
* @param url          请求网络链接
* @param headerMap    请求网络添加头信息
* @param string   请求网络JSON字符串
* @param cacheControl 缓存模式
*
*                     public static final CacheControl FORCE_NETWORK = ..;
*
*                     public static final CacheControl FORCE_CACHE = ...
* @param callback     响应回调
* @param tag          网络任务标识
*/
public void okPostStringRequest(String url, Map<String, String> headerMap, String string, CacheControl cacheControl, Callback callback, String tag) {
//获取Builder
Request.Builder builder = new Request.Builder().url(url);
// 设置缓存
if (cacheControl != null) {
builder.cacheControl(cacheControl);
}
//添加请求头信息
if (headerMap != null && !headerMap.isEmpty()) {
for (Map.Entry<String, String> entry : headerMap.entrySet()) {
builder.addHeader(entry.getKey(), entry.getValue());
}
}
//获取RequestBody
RequestBody requestBody = RequestBody.create(MediaType.parse("text/x-markdown; charset=utf-8"), string);
//获取 Request
Request request = builder.post(requestBody).build();
//获取Call
Call call = mOkHttpClient.newCall(request);
//POST - JSON 设置取消任务标签
mCallHashMap.put(tag, call);
//POST - JSON 发起请求
call.enqueue(callback);
}

案例:

private void postStringFunction() {
//请求链接
String url = "http://192.168.1.107:8080/OkhttpAppLication/test";
//网络请求标识
String tag = "getRequest";

//提交参数
String str = "this is String request data";
//添加请求Header
Map<String, String> heardMap = new HashMap<>();
heardMap.put("verson", "11");
CommonOkhttpUtils.getUtilsInstance().okPostStringRequest(url, heardMap, str, CacheControl.FORCE_NETWORK, new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//请求失败回调方法
}

@Override
public void onResponse(Call call, Response response) throws IOException {
//请求成功回调方法
}
}, tag);
}

提交的数据格式 :



提交的数据原型:



10、POST源码简述:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息