网络框架的简单封装
2017-01-05 13:18
323 查看
一. 前言(简述)
OkHttp是一个高效的HTTP库
Ø 支持 SPDY ,共享同一个Socket来处理同一个服务器所有请求
Ø 如果SPDY不可用,则通过连接池来减少请求延时;
Ø 无缝的支持GZIP来减少数据流量;
Ø 缓存响应数据来减少重复的网络请求。
二简述在项目中使用自己封装的网络框架
1.首先定义一个管理者OkHttpClientManager 这个类采用单例设计模式,直接上代码。
这里给这个client设置了读写超时时间,设置cookie等属性值。
接下来我们就要写常见的Http请求了,当然常见的Http请求用的最多的是get和post啦,下面分别进行封装。
这里我给出了异步的执行post请求,那么这个INetClientHandler 到底是个什么鬼?往下看!
打开INetClientHandler 我们可以看出其实这就是个接口,仔细看看接口定义的几个方法,onSuccess,onFinish,onFailed,onStateFailed等接口回调,是不是感觉有种似曾相识的感觉,没错,我们在HttpUtils里面也知道成功和失败的回调,这里我只是把回调的方法写的详细点,(成功,失败,结束,网络状态异常,服务器异常等情况)。
这段代码主要封装我们的post提交的map,我们把它封装成一个数组,因为往服务器里面传递的数据我用Map来存储。
注:这里的Param封装了键值对
这一段代码相信大家都能看懂,只是封装了一个请求而已,看到这里,我们怎样传一个请求呢,往下看
这部分传递的就是请求结果了,我们把请求后的结果自己去进行操作,来个callback吧!
这里给出了网络状态异常
这里就是我们成功时候的回调啦,client类封装完毕,但我们怎么给出去呢,我们提供了一个方法,调用就可以啦!
这是封装内部做的事情,那么怎么使用呢?这就让NetManager登场啦!
举个栗子
显然这是项目中注册的接口,只需要直接调用就行啦 NetManager.regsiter(),当然我们要传递点参数啦 AbsHashParams 登场,这个类是个抽象类。
我们把每次需要的参数都放在上面的方法,如果需要其他的就重写getOtherParams()方法,返回个map就行了,上面的参数读者不必深究,无外乎就是token 签名 用户id等基础信息,这些读者可以根据自身项目去重新写。
注意:上面说到INetClientHandler ,当然我们不需要时刻的去重写不需要的接口,这违反了设计模式6大原则的内容,即我们不要依赖我们不需要的接口,即接口隔离原则。所以就得重写啦
这里我们给出了具体处理方法,对服务器错误的处理,对网络错误的处理,如果不用就让父类处理,如果想其他的就重写这个方法。处理特殊的需求。至此,本次的封装OkHttp主要的类就到这里了,难免代码有误,请指正。
OkHttp是一个高效的HTTP库
Ø 支持 SPDY ,共享同一个Socket来处理同一个服务器所有请求
Ø 如果SPDY不可用,则通过连接池来减少请求延时;
Ø 无缝的支持GZIP来减少数据流量;
Ø 缓存响应数据来减少重复的网络请求。
二简述在项目中使用自己封装的网络框架
1.首先定义一个管理者OkHttpClientManager 这个类采用单例设计模式,直接上代码。
private static OkHttpClientManager mInstance; public OkHttpClient mOkHttpClient;//可以在程序外调用OkHttpClientManager.mOkHttpClient.cancel private Handler mDelivery; private static final String TAG = "OkHttpClientManager"; private OkHttpClientManager() { mOkHttpClient = new OkHttpClient(); //OkHttp支持连接,读取和写入超时。 mOkHttpClient.setConnectTimeout(10, TimeUnit.SECONDS); mOkHttpClient.setWriteTimeout(10, TimeUnit.SECONDS); mOkHttpClient.setReadTimeout(30, TimeUnit.SECONDS); //cookie enabled一种预定义策略,表示只接受来自原始服务器的 cookie。 mOkHttpClient.setCookieHandler(new CookieManager(null, CookiePolicy.ACCEPT_ORIGINAL_SERVER)); mDelivery = new Handler(Looper.getMainLooper()); } public static OkHttpClientManager getInstance() { if (mInstance == null) { synchronized (OkHttpClientManager.class) { if (mInstance == null) { mInstance = new OkHttpClientManager(); } } } return mInstance; }
这里给这个client设置了读写超时时间,设置cookie等属性值。
接下来我们就要写常见的Http请求了,当然常见的Http请求用的最多的是get和post啦,下面分别进行封装。
/** * 异步的post请求 * * @param url * @param callback * @param params */ private void _postAsyn(String url, final INetClientHandler callback, Map<String, String> params) { Param[] paramsArr = map2Params(params); Request request = buildPostRequest(url, paramsArr); deliveryResult(callback, request); }
这里我给出了异步的执行post请求,那么这个INetClientHandler 到底是个什么鬼?往下看!
public interface INetClientHandler { //状态码为0 表示成功 public void onSuccess(String response); //网络状态异常 public void onNetFail(); //状态码不为0 状态失败,toast错误信息 public void onStateFail(IErrorBody iErrorBody); //只要访问网络成功都会执行此方法 public void onFinish(); //状态码不为0返回的JSON串 public void onFailed(String response); }
打开INetClientHandler 我们可以看出其实这就是个接口,仔细看看接口定义的几个方法,onSuccess,onFinish,onFailed,onStateFailed等接口回调,是不是感觉有种似曾相识的感觉,没错,我们在HttpUtils里面也知道成功和失败的回调,这里我只是把回调的方法写的详细点,(成功,失败,结束,网络状态异常,服务器异常等情况)。
private Param[] map2Params(Map<String, String> params) { if (params == null) return new Param[0]; int size = params.size(); Param[] res = new Param[size]; Set<Map.Entry<String, String>> entries = params.entrySet(); int i = 0; for (Map.Entry<String, String> entry : entries) { res[i++] = new Param(entry.getKey(), entry.getValue()); } return res; }
这段代码主要封装我们的post提交的map,我们把它封装成一个数组,因为往服务器里面传递的数据我用Map来存储。
private Request buildPostRequest(String url, Param[] params) { if (params == null) { params = new Param[0]; } FormEncodingBuilder builder = new FormEncodingBuilder(); for (Param param : params) { if (!CommonUtil.isEmpty(param.value)) { builder.add(param.key, param.value); } } RequestBody requestBody = builder.build(); return new Request.Builder() .url(url) .tag(TAG) .post(requestBody) .build(); }
注:这里的Param封装了键值对
public static class Param { public Param() { } public String key; public String value; public Param(String key, String value) { this.key = key; this.value = value; } }
这一段代码相信大家都能看懂,只是封装了一个请求而已,看到这里,我们怎样传一个请求呢,往下看
private void deliveryResult(final INetClientHandler callback, Request request) { mOkHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(final Request request, final IOException e) { sendFailedStringCallback(request, e, callback); } @Override public void onResponse(final Response response) { try { final String string = response.body().string(); sendSuccessResultCallback(string, callback); } catch (IOException e) { sendFailedStringCallback(response.request(), e, callback); } } }); }
这部分传递的就是请求结果了,我们把请求后的结果自己去进行操作,来个callback吧!
private void sendFailedStringCallback(final Request request, final Exception e, final INetClientHandler callback) { mDelivery.post(new Runnable() { @Override public void run() { if (callback != null) { callback.onNetFail();//记得这里吗 是我们接口定义的回调啊 callback.onFinish(); } } }); }
这里给出了网络状态异常
private void sendSuccessResultCallback(final Object object, final INetClientHandler callback) { mDelivery.post(new Runnable() { @Override public void run() { if (callback != null) { Log.i("test", object.toString()); ResponseBody body = ResponseBody.parse(object.toString()); if (body.isOK()) { callback.onSuccess(object.toString()); callback.onFinish(); } else { IErrorBody ieb = IErrorBody.CODEERROR; ieb.setCode(body.getCode()); ieb.setMessage(body.getMessage()); callback.onFailed(object.toString()); callback.onStateFail(ieb); callback.onFinish(); } } } }); }
这里就是我们成功时候的回调啦,client类封装完毕,但我们怎么给出去呢,我们提供了一个方法,调用就可以啦!
//*************对外公布的方法************ public static void postAsyn(String url, final INetClientHandler callback, Map<String, String> params) { getInstance()._postAsyn(url, callback, params); }
这是封装内部做的事情,那么怎么使用呢?这就让NetManager登场啦!
举个栗子
/** * 注册 * @param absParams * @param handler */ public static void regsiter(AbsHashParams absParams, final INetClientHandler handler){ Map<String,String> map= ParamsHelper.getParams(absParams); OkHttpClientManager.postAsyn(UrlInterface.API_REGISTER, handler, map); }
显然这是项目中注册的接口,只需要直接调用就行啦 NetManager.regsiter(),当然我们要传递点参数啦 AbsHashParams 登场,这个类是个抽象类。
public abstract class AbsHashParams extends AbsParams{ @Override public Map<String, String> getMap() { Map<String,String> map=new HashMap<>(); //传递共有的参数,方便以后封板加密或者增加共有参数 map.put("channel_id", "1"); // if(CommonParams.getSign()!=null){ // map.put("sign", CommonParams.getSign()); // // CommonUtil.getSign(context,"com.luochen.reader") // } map.put("sign", CommonUtil.getSign(AppUtils.getAppContext(),"com.luochen.reader")); map.put("device_id", CommonParams.getDevice_id()); map.put("timestamp", System.currentTimeMillis() + ""); if(StringUtils.isValid(CommonParams.getToken())){ map.put("uid", CommonParams.getUid()); map.put("token", CommonParams.getToken()); } // map.put("uid", CommonParams.getUid()); // map.put("token", CommonParams.getToken()); getOtherParams(map); return map; } public abstract Map<String, String> getOtherParams(Map<String,String> map); }
我们把每次需要的参数都放在上面的方法,如果需要其他的就重写getOtherParams()方法,返回个map就行了,上面的参数读者不必深究,无外乎就是token 签名 用户id等基础信息,这些读者可以根据自身项目去重新写。
注意:上面说到INetClientHandler ,当然我们不需要时刻的去重写不需要的接口,这违反了设计模式6大原则的内容,即我们不要依赖我们不需要的接口,即接口隔离原则。所以就得重写啦
public class NetClientHandler implements INetClientHandler { private Context context; public NetClientHandler(@NonNull Context context) { this.context = context; } @Override public void onSuccess(String response) { Log.i("test", "response=" + response); } @Override public void onNetFail() { if (context != null) { // ToasterHelper.show(context, "您的网络异常,请检查网络!!"); Toast.makeText(context,"您的网络异常,请检查网络!!",Toast.LENGTH_SHORT).show(); } // else if (TUtils.isValid(AppUtils.getAppContext())) { // ToasterHelper.show(context, "您的网络异常,请检查网络!!"); // } } @Override public void onStateFail(IErrorBody iErrorBody) { if (!CommonUtil.isEmpty(iErrorBody)) { if(iErrorBody.getMessage()!=null){ // ToasterHelper.show(context.getApplicationContext(), iErrorBody.getMessage().toString()); Toast.makeText(context,iErrorBody.getMessage().toString(),Toast.LENGTH_SHORT).show(); } } if (iErrorBody.getCode() == 1008) { return; } else { if (!CommonUtil.isEmpty(iErrorBody.getMessage())) // ToasterHelper.show(context, iErrorBody.getMessage()); Toast.makeText(context,iErrorBody.getMessage(),Toast.LENGTH_SHORT).show(); } } @Override public void onFinish() { } @Override public void onFailed(String response) { } }
//注册 NetManager.regsiter(new AbsHashParams() { @Override public Map<String, String> getOtherParams(Map<String, String> map) { //所有传递的数据 map.put("username","yuan"); map.put("password","123"); return map; } }, new INetClientHandler() { @Override public void onSuccess(String response) { //成功时 response返回的json } @Override public void onNetFail() { //网络失败时 } @Override public void onStateFail(IErrorBody iErrorBody) { //服务器异常 } @Override public void onFinish() { //结束时 这里可以给出关闭提示框等等 } @Override public void onFailed(String response) { //失败时 } });
这里我们给出了具体处理方法,对服务器错误的处理,对网络错误的处理,如果不用就让父类处理,如果想其他的就重写这个方法。处理特殊的需求。至此,本次的封装OkHttp主要的类就到这里了,难免代码有误,请指正。
相关文章推荐
- iOS 对基于AFNetworking框架网络请求的简单封装
- 给Android封装的一个简单网络请求框架
- 优雅设计封装基于Okhttp3的网络框架(二):多线程下载功能原理设计 及 简单实现
- Android 网络访问框架retrofit2,okhttp3之简单封装,kotlin源码
- Android网络框架之----OKHttp简单二次封装
- Android----------OkHttp网络请求框架Get和Post简单封装(泛型)
- 网络通讯框架MINA和XSCOCKET的简单比较
- Ios开发对第三方框架AFNetWorking网络访问的封装使用
- 一个非常简单的.net网络通信框架XNetFramework(符源码与测试Demo)
- C/S架构移动网络Socket API接口 Socket网络库 xNet框架介绍(C++封装) Demo演示示例
- 网络通讯框架mina和xscocket的简单比较
- 高并发MINA框架,网络编程(SOCKET)实现,简单的网络聊天DEMO
- 对iOS网络请求的简单封装,并且使用block回调函数方式
- 自己封装的android客户端http网络框架
- Android使用Google推荐的联网框架Volley,让连接网络更加简单
- Android_访问网络三(android-async-http框架的简单使用)
- acl_cpp 简单实用、功能强大的C++网络应用与服务器框架库发布
- 一个非常简单的.net网络通信框架XNetFramework(符源码与测试Demo)
- Android 网络通信框架Volley的简单使用
- iOS网络请求第三方框架:MKNetworkKit介绍及简单使用