可扩展,兼容多种网络请求框架的方案!!!
2016-03-10 14:42
381 查看
NetWorkUtils
这篇博客的初衷是为了自己的一个开源项目而写的—NetWorkUtis,现在是1.0版本,肯定会有有不少设计或者是代码方面的问题,大家去看看,提点意见。看标题就知道,是关于Android 网络请求方面的问题。
Android的网络请求技术一直以来发展迅速,官方,民间大神,特别是接下来,全世界的网络基础的快速部署和升级,而每个人又少不了升级,业务推动技术。
根据官方的说法,是在Android2.3之前HttpUrlConnection类库是存在问题的,例如连接池的问题。所以,在Android2.3以前是推荐使用HttpClient类库,但是是Apache之前在JAVA平台上的类库,好用是好用,但是与Android系统,在性能优化和兼容方面的工作量大,谷歌的工程师们并不是推荐(因为他们不知道什么时候会去升级HttpClient)。
后来,谷歌又推出了Volley,Volley就是在2.3以前调用HtttpClient,2.3以后调用的HttpUrlConnection,证明,谷歌方面还是比较推荐HttpUrlConnection的.那么问题来了,挖…不,Android网络层到底用什么?不是说谷歌在2.3以后调用了HttpUrlConnection么?
为什么有这样的一个问题呢?因为Square公司推出了OkHttp.并且在短时间几乎漫延到了世界各地,因为Square公司开源的质量都是顶级的,推动了Android一步又一步发展的,经历了实际业务的考验的。Android在4.4之后使用okHttp来进行一个网络连接的替换。Volley也听说停止了维护。
那么,现在摆在我们面前的就有三个主流选择(因为主要的网络底层协议库是这些,大部分的网络库是应用层的)。
HttpClient
HttpUrlConnection
OkHttp
但是,现在的一个最佳选择,随着技术的发展,最终会产生他的替代品,可能需要漫长的时间,也可能短短几个月或者一年就会发生。那么,之前因为选择的技术残留在项目中,我们就不能很快的进行更换。
举个栗子:Android6.0删除HttpClient对大家项目影响应该是蛮大的,不过因为6.0系统占有比例小,使用了HttpClient的大家现在不急着修改,而且很大一部分开发者应该会选择加入HttpClient的jar,这样比较丑陋的解决方案。
所以,我就萌生(-_-||| )了这个项目的想法。
而我的设计想法主要来源于两个点:
一个是一些网络图片加载库的可以替换网络层,或者自定义网络层的做法。
第二个是下拉刷新框架android-Ultra-Pull-To-Refresh的写法。廖祜秋大神将实现上拉,松开等的操作抽象出来形成接口,这个样的话,当项目需要或者自己心血来潮,想实现一个新的下拉动画,就轻而易举了。
public interface PtrUIHandler { /** * When the content view has reached top and refresh has been completed, view will be reset. * * @param frame */ public void onUIReset(PtrFrameLayout frame); /** * prepare for loading * * @param frame */ public void onUIRefreshPrepare(PtrFrameLayout frame); /** * perform refreshing UI */ public void onUIRefreshBegin(PtrFrameLayout frame); /** * perform UI after refresh */ public void onUIRefreshComplete(PtrFrameLayout frame); public void onUIPositionChange(PtrFrameLayout frame, boolean isUnderTouch, byte status, PtrIndicator ptrIndicator); }
我想,网络层应该也可以,抽象出一个通用的抽象类,内部实现由具体的子类实现,然后定义一个固定的网络方法类,来调用继承了抽象类的子类,或者进行内部的网络层的替换。
public abstract class NetWork<T> { public abstract void post(HashMap<String, String> paramsMap, String url,NetWorkCallback<T> callback, Object tag, int... what); public abstract void get(HashMap<String, String> paramsMap, String url,NetWorkCallback<T> callback, Object tag, int... what); public abstract void uploadFile(String uploadUrl, HashMap<String, String> paramsMap, String fileKey, File file, NetWorkCallback<T> callback, Object uploadFileTag, int... what); public abstract void uploadFiles(String uploadUrl, HashMap<String, String> paramsMap, ArrayList<String> fileKeys, ArrayList<String> fileNames, ArrayList<File> files, NetWorkCallback<T> callback, Object uploadFileTag, int... what); public abstract void downLoadFile(String downUrl, String savePath, String saveFileName, long connTimeOut, long readTimeOut, long writeTimeOut,NetWorkCallback<T> callBack, Object downFileTag, int... what); public abstract void cancel(Object tag); }
现在这个公共的父类还是存在的一个小小的耦合问题,int… what参数还是比较丑陋的(为了兼容一下Nohttp[NoHttp底层是采用HttpUrlConnection实现的],因为这个是他独特的,而且是一个比较好的设计)。
然后,我通过公共的HttpResponse来兼容其余网络库的HttpResponse
public abstract class NetWorkResponse<T> { public abstract String getString(); public abstract T getObj(Class<T> cls); public abstract Object getResponse(); }
当使用着需要某些网络层特定的功能的时候,就需要自己去获取Response或者Request了。这些都将由子类来暴露接口或者具体的实现。
以NoHttp举个栗子,恩,先给大家介绍一下Nohttp的传送门,博客,是已经开源在github上的,而且作者最近星期六星期天还直播NoHttp的代码讲解,大家可以去看啊,恩,直播打代码,想想都带感。
public class NoHttpNetWork<T> extends NetWork<T> { @Override public void post(HashMap<String, String> paramsMap, String url,NetWorkCallback<T> callback, Object tag, int... what) { netWork(paramsMap, url, RequestMethod.POST, callback, tag, what); } public Request netWork(HashMap<String, String> paramsMap, String url, RequestMethod method, NetWorkCallback<T> callback, Object tag, int... what) { Request request= putParameter(paramsMap,url,method,tag); netWork(request, callback, what); return request; } public void netWork(Request request, NetWorkCallback<T> callback, int... what) { OnResponseListener onResponseListener = convertNetWorkCallback(callback); if (what.length == 0) { throw new IllegalArgumentException("what is null?"); } requestQueue.add(what[0], request, onResponseListener); } }
大家普遍使用的post方法由父类指定要求实现,如果有特殊需求的话,例如nohttp,在request中,有一些独特的方法:
Object remove(String key); void removeAll(); T parseResponse(String url, Headers responseHeaders, byte[] responseBody);
如果需要使用的话,就需要子类将request返回,就要调用NoHttpNetWork.network方法,当然,大家都知道,这是父类不需要理会的。
而网络请求中的回调,则也采取了通用的方法,通过抽取公共的回调方法,让使用着在具体处理上无需考虑更多。
public abstract class NetWorkCallback<T> { public abstract void onStart(int NoHttpWhat); public abstract void onFinish(int NoHttpWhat); public abstract void onSucceed(NetWorkResponse<T> response,int NoHttpWhat); public abstract void onError(NetWorkError netWorkError); public abstract void onProgress(float progress, long fileCount,int NoHttpWhat); }
恩,这里还是一样,NoHttpWhat还是比较显眼,而且也暴露了一个问题,也是为我正在思考的:如果某一个网络层例如NoHttp有一个独特的设计参数,这一个是很难兼容的。当然这个也是一个通用的Callback,现阶段就暂时不去管NoHttpWhat了,等想到优雅的解决方案在说。
当需要扩展某个网络层的时候,也可以自定义Callback。例如为扩展OkHttp,为就可以让使用okHttp的时候不去理会NoHttpWha。
public abstract class OkCallBack<T> extends NetWorkCallback<T> { public abstract void onStart(); public abstract void onFinish(); public abstract void onSucceed(NetWorkResponse<T> response); public abstract void onProgress(float progress, long fileCount); @Override public void onStart(int NoHttpWhat) { onStart(); } @Override public void onFinish(int NoHttpWhat) { onFinish(); } @Override public void onSucceed(NetWorkResponse<T> response, int NoHttpWhat) { onSucceed(response); } @Override public void onProgress(float progress, long fileCount, int NoHttpWhat) { onProgress(progress, fileCount); } }
当然,如果我想到了解决兼容参数的方法后,我还是不建议大家使用自定义Callback。
之前说过,这个项目就是为了在替换网络库的时候的减少甚至没有代码修改,如果使用自定义callback,可能效果就没有那么好了。
大概就是这样了,总结一下,将项目分为几层:
供使用者直接调用一层,提供项目接口调用,我称呼为NetWorkUtils,改动应该是微乎其微的(为了项目的持续发展,当有更好的解决方案,是必不可少添加上去的)。
NetWorkUtils调用抽象网络请求层,我称为NetWork层。在NetWorkUtils层提供一个变量,供使用者初始化NetWork层。
Callback层,兼容不同的网络库中的回调或者监听。
其余的都是些兼容的小细节了。写到这里,突然想起现在的一个趋势:用WebAPP来代替原生态开发,也是兼容的路子。我这个也是有一点点赶上时代的潮流么?
其实感觉就想是一个代理的模式,把okhttp、httpUrlConnection当做美国,法国等国家的网络,使用者就是’防火墙’里面的人,要出去看一看的话,总是得弄一个梯子,梯子来帮你兼容和打开各国的网络。
不过,WebAPP是跨平台兼容,我只是兼容一下类库的使用,差之甚远啊。
因为会存在只使用某一个网络库或者想自己扩展的,所以我将原型与扩展分开来了。
原型设计: NetWorkUtils
具体实现: NetWorkUtils-extend
转载请注明出处
相关文章推荐
- 统计Apache的并发请求数及其TCP连接状态
- [转] 详解http和https的作用与区别
- Apache JMeter HTTPS(S) Test Script Recorder
- Linux网络编程--定时器的学习和使用
- UNP卷一学习笔记:TCP服务器常见故障
- 卷积神经网络
- SwipeRefreshLayout+AsyncHttpClient 实现异步Http请求的下拉刷新
- 安卓之HTTPSMD5加密
- C# 的TCPClient异步连接与异步读数据
- python 发起HTTP请求
- 解决HTTP Status 500 - java.lang.NoClassDefFoundError: org/apache/commons/el/ExpressionEvaluatorImpl报错
- TCP/IP通信程序设计方式
- Linux服务器上监控网络带宽的18个常用命令
- http客户端通信 (java原生)
- angularjs flask跨域问题 XMLHttpRequest cannot load. No 'Access-Control-Allow-Origin'
- 安卓之检测网络
- ndroid获取网络时间及时间日期显示格式
- TCP/IP知识总结(TCP/IP协议族读书笔记四)
- tcp-ip-状态详解(转)
- Java多线程TCP客户端与服务器间使用Socket通信