前言:
提及访问网络,很自然的会用到okHttp,虽然okhttp已经封装的比较完善,
调用也比较方便,但对于向我这样比较懒的人,okhttp的调用还是略显复杂,
每次都要写同样重复的代码,简直不能忍受,那就封装以下一句话调用完毕,岂不快哉。。。
废话不多说,请抓稳扶好,老司机,走起。。。
重要的事情提一提:看不懂的文章最后有完整代码,看看完整版应该就没问题了。
okHttp使用流程
没有什么是一张图说不清的,走起
高逼格的封装开始
网络访问框架一般都需要单例模式(singleton),首先我们也进行单利模式。
1 首先私有化构造器,让别人不能new出其它实例。
2 声明该类的一个静态成员变量实例,本篇为instance
3 声明一个公有的方法getInstance提供给调用者本类实例。
/**
* 网络访问要求singleton
*/
private static OkHttpUtils instance;
// 必须要用的okhttpclient实例,在构造器中实例化保证单一实例
private OkHttpClient mOkHttpClient;
private OkHttpUtils() {
/**
* okHttp3中超时方法移植到Builder中
*/
mOkHttpClient = (new OkHttpClient()).newBuilder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.build();
}
public static OkHttpUtils getInstance() {
if (instance == null) {
synchronized (OkHttpUtils.class) {
if (instance == null) {
instance = new OkHttpUtils();
}
}
}
return instance;
}
上面代码在构造器中实例化出了okHttpClient的实例,既然我们这个帮助类是单例的,那么构造器中的okHttpClient也只会走一次,必定也是单实例的。
提供GET和POST两种访问方式的方法
既然是工具类,肯定要更加简单,此处我们需要提供针对GET和POST两种方式的访问方法。
1.工具类为GET访问方式提供的方法
/**
* 对外提供的Get方法访问
* @param url
* @param callBack
*/
public void Get(String url, MyCallBack callBack) {
/**
* 通过url和GET方式构建Request
*/
Request request = bulidRequestForGet(url);
/**
* 请求网络的逻辑
*/
requestNetWork(request, callBack);
}
2.工具类为POST访问方式提供的方法(表单数据)
/**
* 对外提供的Post方法访问
* @param url
* @param parms: 提交内容为表单数据
* @param callBack
*/
public void PostWithFormData(String url, Map<String, String> parms, MyCallBack callBack) {
/**
* 通过url和POST方式构建Request
*/
Request request = bulidRequestForPostByForm(url, parms);
/**
* 请求网络的逻辑
*/
requestNetWork(request, callBack);
}
3.工具类为POST访问提供方法(JSON数据)
/**
* 对外提供的Post方法访问
* @param url
* @param json: 提交内容为json数据
* @param callBack
*/
public void PostWithJson(String url, String json, MyCallBack callBack) {
/**
* 通过url和POST方式构建Request
*/
Request request = bulidRequestForPostByJson(url, json);
/**
* 请求网络的逻辑
*/
requestNetWork(request, callBack);
}
从这两个方法,我们能看到我们需要构建GET和POST访问方式对应的Request对象和我们自定义的MycallBack接口,下面先来看一下构建Request对象。
构建Request对象
为了大家更好的理解封装流程,首先请大家回顾一下okhttp的使用流程:
mOkHttpClient.newCall(request).enqueue(new Callback() {})
1.首先我们来看构建GET需要的Request对象,这个也是最简单的。
/**
* GET方式构建Request
* @param url
* @return
*/
private Request bulidRequestForGet(String url) {
return new Request.Builder()
.url(url)
.get()
.build();
}
2.构建提交表单数据的Request对象
/**
* POST方式构建Request {Form}
* @param url
* @param parms
* @return
*/
private Request bulidRequestForPostByForm(String url, Map<String, String> parms) {
FormBody.Builder builder = new FormBody.Builder();
if (parms != null) {
for (Map.Entry<String, String> entry :
parms.entrySet()) {
builder.add(entry.getKey(), entry.getValue());
}
}
FormBody body = builder.build();
return new Request.Builder()
.url(url)
.post(body)
.build();
}
3.构建提交json数据的Request对象
/**
* POST方式构建Request {json}
* @param url
* @param json
* @return
*/
private Request bulidRequestForPostByJson(String url, String json) {
RequestBody body = RequestBody.create(JSON, json);
return new Request.Builder()
.url(url)
.post(body)
.build();
}
开始处理联网逻辑
上述代码及分析基本上把简单封装的东西讲完了,有了okhttpclient和request对象我们需要处理联网逻辑了,也就是上述的 requestNetWork方法。
private void requestNetWork(Request request, MyCallBack callBack) {
/**
* 处理连网逻辑,此处只处理异步操作enqueue
*/
callBack.onLoadingBefore(request);
mOkHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
callBack.onFailure(request, e);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
callBack.onSuccess(response);
} else {
callBack.onError(response);
}
}
});
}
MyCallBack对象分析
看到此处,估计有人会一脸懵逼,这个MyCallBack是个什么鬼。
其实这是我定义的一个接口,那么为什么要定义她呢。因为我们在使用我们的工具类的时候,访问网络成功后肯定会有数据返回,我们怎么处理呢,okhttp内部通过一个callBack把数据回调回来,那么我们自己封装的工具类不妨仿照他的做法 定义一个接口回调Response的内容。贴一下接口的内容
interface MyCallBack {
void onLoadingBefore(Request request);
void onSuccess(Response response);
void onFailure(Request request, Exception e);
void onError(Response response);
}
封装进阶
看到此处,觉得封装已经完结了,不不不,还有一个重要的问题,不处理的话会导致崩溃的,这个问题就是,我们定义接口回调的地方是在子线程,而我们的Response很明显需要拿回到主线程进行UI的更新,所以访问网络的方法requestNetWork需要通过Handler把子线程的Resonse发送到主线程,请看详细实现。
private void requestNetWork(Request request, MyCallBack callBack) {
/**
* 处理连网逻辑,此处只处理异步操作enqueue
*/
callBack.onLoadingBefore(request);
mOkHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
mHandler.post(() -> callBack.onFailure(request, e));
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
mHandler.post(() -> callBack.onSuccess(response));
} else {
mHandler.post(() -> callBack.onError(response));
}
}
});
}
结束语
此工具类还没有完善,下篇文章继续完善,待完善内容:返回Resonpse直接解析成javaBean返回。
完整代码
public class OkHttpUtils {
/**
* 网络访问要求singleton
*/
private static OkHttpUtils instance;
// 必须要用的okhttpclient实例,在构造器中实例化保证单一实例
private OkHttpClient mOkHttpClient;
public static final MediaType JSON = MediaType.
parse("application/json; charset=utf-8");
private Handler mHandler;
private OkHttpUtils() {
/**
* okHttp3中超时方法移植到Builder中
*/
mOkHttpClient = (new OkHttpClient()).newBuilder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.build();
mHandler = new Handler(Looper.getMainLooper());
}
public static OkHttpUtils getInstance() {
if (instance == null) {
synchronized (OkHttpUtils.class) {
if (instance == null) {
instance = new OkHttpUtils();
}
}
}
return instance;
}
/**
* 对外提供的Get方法访问
* @param url
* @param callBack
*/
public void Get(String url, MyCallBack callBack) {
/**
* 通过url和GET方式构建Request
*/
Request request = bulidRequestForGet(url);
/**
* 请求网络的逻辑
*/
requestNetWork(request, callBack);
}
/**
* 对外提供的Post方法访问
* @param url
* @param parms: 提交内容为表单数据
* @param callBack
*/
public void PostWithFormData(String url, Map<String, String> parms, MyCallBack callBack) {
/**
* 通过url和POST方式构建Request
*/
Request request = bulidRequestForPostByForm(url, parms);
/**
* 请求网络的逻辑
*/
requestNetWork(request, callBack);
}
/**
* 对外提供的Post方法访问
* @param url
* @param json: 提交内容为json数据
* @param callBack
*/
public void PostWithJson(String url, String json, MyCallBack callBack) {
/**
* 通过url和POST方式构建Request
*/
Request request = bulidRequestForPostByJson(url, json);
/**
* 请求网络的逻辑
*/
requestNetWork(request, callBack);
}
/**
* POST方式构建Request {json}
* @param url
* @param json
* @return
*/
private Request bulidRequestForPostByJson(String url, String json) {
RequestBody body = RequestBody.create(JSON, json);
return new Request.Builder()
.url(url)
.post(body)
.build();
}
/**
* POST方式构建Request {Form}
* @param url
* @param parms
* @return
*/
private Request bulidRequestForPostByForm(String url, Map<String, String> parms) {
FormBody.Builder builder = new FormBody.Builder();
if (parms != null) {
for (Map.Entry<String, String> entry :
parms.entrySet()) {
builder.add(entry.getKey(), entry.getValue());
}
}
FormBody body = builder.build();
return new Request.Builder()
.url(url)
.post(body)
.build();
}
/**
* GET方式构建Request
* @param url
* @return
*/
private Request bulidRequestForGet(String url) {
return new Request.Builder()
.url(url)
.get()
.build();
}
private void requestNetWork(Request request, MyCallBack callBack) {
/**
* 处理连网逻辑,此处只处理异步操作enqueue
*/
callBack.onLoadingBefore(request);
mOkHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
mHandler.post(() -> callBack.onFailure(request, e));
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
mHandler.post(() -> callBack.onSuccess(response));
} else {
mHandler.post(() -> callBack.onError(response));
}
}
});
}
}
定义的接口的完整代码
interface MyCallBack {
void onLoadingBefore(Request request);
void onSuccess(Response response);
void onFailure(Request request, Exception e);
void onError(Response response);
}