OkHttp框架二次封装,post json格式的参数(上)
请求的封装
本篇主要是针对后台数据格式,进行请求参数的封装。封装的目的,是为了配合后台的数据结构,方便客户端进行数据的请求和响应数据的处理。
数据请求的格式
数据请求的请求以Json格式传递参数到服务器,在本例中,参数分为了公参和私参,请求体结构如下:
{
"args": {
"pri_args": {
"username": "xxxxxx",
"password": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
"pub_args": {
"appversion": "xxx",
"imei": "xxxxxxxx",
"token": "xxxxxxxx",
"uid": xxxxxx
}
}
}
在使用过程时,首先要做的,是对参数的拼接,将私有参数和公参分开来,对于整个APP来说,只要登录了,每次请求接口时,公参都是相对固定的,因此可以把公参隐藏起来,让用户不必每次请求都自己写公参传进去,只需要在app打开的时候给公参赋值,然后对于每个接口,只需要传私参即可。
说在前面的话
项目使用的是鸿洋大神封装好的Okhttp-utils框架,针对Json格式的数据请求,进行了二次封装,膜拜大神!下面是原来的框架地址:
博客地址:http://blog.csdn.net/lmj623565791/article/details/47911083
github:https://github.com/hongyangAndroid/okhttp-utils
遵循开闭原则,二次封装并没有对原来的框架动刀子,只是把原来的框架作为依赖,在此基础上,进行了二次封装而已。
【Look here】:由于后台定义的请求格式各有不同,返回字段也各有差异,args、pri_args、pub_args等这些字段都不会一样,所以本文章封装的框架可能不能直接拿来就用,但是可以参照我这边封装的,照葫芦画瓢,本篇只介绍自己封装时的想法和写过之后的经验,谈不上技术分享,大家酌情参考。
参数的拼接
虽然原来的Okhttp-utils里并没有直接对json格式参数的封装,但是有对String类型参数的封装方法postString,我们可以借用这个方法,然后在这个方法里再封装一层,达到的效果是,使用时,传进去的是Map
OkHttpUtils.postString().url(THost.HOST).content(paramContent).build().execute(callback);
使用时传入url和content,然后可以看到postString实际上是返回了一个PostStringBuilder类型的对象实例.
OkHttpUtils.java
public static PostStringBuilder postString() {
return new PostStringBuilder();
}
然后通过这个对象的build方法,传入url和content参数,生成了一个RequestCall对象。
PostStingBuilder.java
public RequestCall build() {
return (new PostStringRequest(this.url, this.tag, this.params, this.headers, this.content, this.mediaType, this.id)).build();
}
OkHttpRequest.java
public RequestCall build() {
return new RequestCall(this);
}
最后调用execute方法来发送请求,并且给这个方法传了两个参数,一个是刚刚生成的RequestCall对象,另一个就是自己定义的Callback了。
public void execute(final RequestCall requestCall, Callback callback)
{
......
}
我们要做的工作是:
1、给框架使用者提供方法,来传入Map类型的参数;
2、转换传入的参数,将其变成json string
3、将得到的json string 通过postString方法发送出去
无论是传参还是转换,都可以在Builder里去写:
我们可以以PostStringBuilder类为模板新建一个PostJsonBuilder类:
public class TPostJsonBuilder extends OkHttpRequestBuilder<TPostJsonBuilder> {
private String paramContent;
private MediaType mediaType;
private Map<String, Object> pri_args;
private Map<String, Object> pub_args;
public TPostJsonBuilder() {
this.pri_args = new HashMap<>() ;
this.pub_args = new HashMap<>() ;
}
public TPostJsonBuilder(String paramContent, Map<String, Object> pri_args, MediaType mediaType, Map<String, Object> pub_args) {
this.paramContent = paramContent;
this.pri_args = pri_args;
this.mediaType = mediaType;
this.pub_args = pub_args;
}
public TPostJsonBuilder pri_args(Map<String, Object> args) {
this.pri_args = args ;
return this;
}
public TPostJsonBuilder pub_args(Map<String, Object> args) {
this.pub_args = args ;
return this;
}
public TPostJsonBuilder paramContent(String content) {
if (content != null) {
this.paramContent = content;
} else if (this.pri_args.size() != 0 && this.pub_args.size() != 0){
this.paramContent = initParams(this.pri_args,this.pub_args) ;
} else {
Exceptions.illegalArgument("args cannot be null !");
}
return this;
}
//这个方法就是拼接参数的关键了,将传入的公参和私参拼接成json string
private String initParams(Map<String, Object> pri_args, Map<String, Object> pub_args) {
Map<String,Map<String, Object>> priArgs = new HashMap<>();
priArgs.put("pri_args",pri_args);
Map<String,Map<String, Object>> pubArgs = new HashMap<>();
pubArgs.put("pub_args",pub_args);
Map<String,Map<String,Map<String, Object>>> args = new HashMap<>() ;
//将pub_args追加到pri_args里
priArgs.putAll(pubArgs);
args.put("args",priArgs);
Gson g = new Gson();
String argsStr = g.toJson(args) ;
return argsStr ;
}
public TPostJsonBuilder mediaType(MediaType mediaType)
{
this.mediaType = mediaType;
return this;
}
@Override
public RequestCall build() {
paramContent = initParams(this.pri_args,this.pub_args) ;
mediaType = MediaType.parse("application/json;charset=utf-8") ;
return new PostStringRequest(url,tag,params,headers,paramContent,mediaType,id).build();
}
}
里面将参数分为私参pri_args和公参pub_args两部分,并且给这个两个参数暴露了返回值为TPostJsonBuilder对象的方法,这样使用者就可以通过.pri_args(pri).pub_args(pub)来传入参数;
然后在关键的initParams方法里,将私参和公参拼接成服务器所需要的形式,然后再转成json string,在build方法里通过PostStringRequest构建RequestCall。这样参数的封装就基本完成了。
然后就是给使用者暴露postJson方法了,我们写一个类继承自OkHttpUtils:
TOkhttpUtil.java
public class TOkhttpUtil extends OkHttpUtils {
public static void initPubParams(Map<String, Object> pub_args) {
TPublicParam.publicparam = pub_args ;
}
public static void initHeadS(String s) {
TPublicParam.headparam.put("s",s) ;
}
public TOkhttpUtil(OkHttpClient okHttpClient) {
super(okHttpClient);
}
public static TPostJsonBuilder postJson() { return new TPostJsonBuilder(); }
}
里面有一个方法postJson,用来返回一个TPostJsonBuilder对象。
还有两个方法,initPubParams和initHeadS,这两个方法就是对于公参和请求头的封装了。本例中,请求头里有2个字段,s字段相对不变,m字段每个接口都不同,所以可以先封装好s,下面会说到。
这样TOkhttUtil就可以这么使用了:
TOkhttpUtil.postJson().url(THost.HOST).pri_args(pri_args).pub_args(pub_args).build().execute(callback)
其中的pri_args和pub_args分别是要传的公参和私参,例如:
Map<String,Object> pri_args = new HashMap<>();
pri_args.put("username","张三");
pri_args.put("password","4f32d39b42v322vkj43");
Map<String,Object> pub_args = new HashMap<>();
pub_args.put("appversion","1.0.1");
pub_args.put("imei","0000-0033-3300-3232-9909-3333");
pub_args.put("token","4f32d39b42v322vkj43");
pub_args.put("uid",9527);
就可以得到文章开头所要传的参数格式。
参数的封装
虽然能请求了,但是公参里面的值大多不变,每次调用方法都要传pub_args也不好,所以还是可以通过封装参数,然后暴露多个重载方法,
让用户用的更省心:
TBaseApi.java
public class TBaseApi {
//最原始的方法,传url,请求头,私参,公参,回调
public static void createPostRequest(String url, Map<String,String> heads, Map<String,Object> pri_args, Map<String,Object> pub_args, TBaseCallback callback){
TOkhttpUtil.postJson()
.url(url)
.headers(heads)
.pri_args(pri_args)
.pub_args(pub_args)
.build()
.execute(callback) ;
}
//封装了公参,使用时不用传公参了。
public static void createPostRequest(String url, Map<String,String> heads, Map<String,Object> pri_args, TBaseCallback callback){
TOkhttpUtil.postJson()
.url(url)
.headers(heads)
.pri_args(pri_args)
.pub_args(TPublicParam.publicparam)
.build()
.execute(callback) ;
}
//使用固定的HOST
public static void createPostRequest(Map<String,String> heads, Map<String,Object> pri_args, TBaseCallback callback){
TOkhttpUtil.postJson()
.url(THost.HOST)
.headers(heads)
.pri_args(pri_args)
.pub_args(TPublicParam.publicparam)
.build()
.execute(callback) ;
}
//封装请求头里面的s字段,只需传m字段就行了。
public static void createPostRequest(String headM, Map<String,Object> pri_args, TBaseCallback callback){
TOkhttpUtil.postJson()
.url(THost.HOST)
.headers(TPublicParam.addHeadM(headM))
.pri_args(pri_args)
.pub_args(TPublicParam.publicparam)
.build()
.execute(callback);
}
}
上面的方法里,提供了多个选择,TPublicParam里封装好了公参。在使用的时候,只需要在初始化的时候,同时把固定的公参和私参也加进去:
比如在TApplication.java里初始化:
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(10*1000L, TimeUnit.MILLISECONDS)
.readTimeout(10*1000L, TimeUnit.MILLISECONDS)
.build();
TOkhttpUtil.initClient(client) ;
TOkhttpUtil.initPubParams(TPublicParam.addPublicParams(pubParams));
TOkhttpUtil.initHeadS(TConstants.getS());
这样,以后在调用时,可以只传最低限度的参数,比如请求头的m字段,私参,和自定义的callback,已经封装好的头部的s字段和公参就不需要操心了。
比如:
Map<String,Object> pri_args = new HashMap();
TBaseCallback callback = new ....
TBaseApi.createPostRequest("getUserInfo",pri_args,callback) ;
下篇里会介绍响应的封装,以及TBaseCallback是什么。有兴趣可以看看下篇:
http://blog.csdn.net/black_dreamer/article/details/53068627
github地址:https://github.com/herdotage/Android_sample/tree/master/LOkhttpUtils