您的位置:首页 > 理论基础 > 计算机网络

可扩展,兼容多种网络请求框架的方案!!!

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

转载请注明出处
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: