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
转载请注明出处