本文为原创,转载请写明出处,[原文链接](http://blog.csdn.net/qq_33737742)
本文为原创,转载请写明出处,[原文链接](http://blog.csdn.net/qq_33737742)
1,先描述一下需求
目前正在用的http请求是Xutils,现在发现使用OkHttp来封装一套会更好。又比方说,目前正在用的数据存储方案是OrmLite,
现在使用greenDao或者Realm会更好,在类似这些情况下,如何做到不修改Activity/Fragment/Presenter代码的情况下,
把Volley的http请求实现更换成Okhttp的实现,把OrmLite更换成greenDao或者Realm?
解决问题的关键词:设计模式中的——工厂方法模式。下面我说一下我的思路
1.把Xutils中的http请求框架的共性方法抽取到接口中,我们把这个接口称为“请求接口”;
2.创建一个用于返回请求结果的接口,我们把这个接口称为“回调接口”;
3.分别用Volley和OkHttp实现“请求接口”;
4.创建一个类来返回上述接口的对象,我们把这个类叫做“工厂”类;
5.在Activity/Fragment/Presenter中,使用“工厂”返回的这个接口对象调用get/post/put/delete方法,并在“回调接口”中得到请求结果。
直接上代码
1.把共性方法抽取到接口中
/**
* Created by lvfeifei on 2016/12/11.
*/
public interface IRequestManager {
<T> Callback.Cancelable get(String url, Map<String, String> map, Callback.CommonCallback<T> callback);
<T> Callback.Cancelable post(String url, Map<String, Object> map, Callback.CommonCallback<T> callback);
<T> Callback.Cancelable UpLoadFile(String url, Map<String, Object> map, Callback.CommonCallback<T> callback);
<T> Callback.Cancelable DownLoadFile(String url, String filepath, Callback.CommonCallback<T> callback);
}
2.用Xutils的联网请求类XUtilsRequestManager实现这个接口,我这里写了四个方法
/**
* Created by 吕飞飞 on 2016/12/23.
* 用于封装XUtils联网和上传下载文件
*/
public class XUtilsRequestManager implements IRequestManager {
public static XUtilsRequestManager getInstance() {
return SingletonHolder.INSTANCE;
}
private static class SingletonHolder {
private static final XUtilsRequestManager INSTANCE = new XUtilsRequestManager();
}
/**
* 发送get请求
*
* @param <T>
*/
@Override
public <T> Callback.Cancelable get(String url, Map<String, String> map, Callback.CommonCallback<T> callback) {
RequestParams params = new RequestParams(url);
params.setConnectTimeout(5000);
if (null != map) {
for (Map.Entry<String, String> entry : map.entrySet()) {
params.addQueryStringParameter(entry.getKey(), entry.getValue());
}
}
Callback.Cancelable cancelable = x.http().get(params, callback);
return cancelable;
}
/**
* 发送post请求
*
* @param <T>
*/
@Override
public <T> Callback.Cancelable post(String url, Map<String, Object> map, Callback.CommonCallback<T> callback) {
RequestParams params = new RequestParams(url);
if (null != map) {
for (Map.Entry<String, Object> entry : map.entrySet()) {
params.addParameter(entry.getKey(), entry.getValue());
}
}
Callback.Cancelable cancelable = x.http().post(params, callback);
return cancelable;
}
/**
* 上传文件
*
* @param <T>
*/
@Override
public <T> Callback.Cancelable UpLoadFile(String url, Map<String, Object> map, Callback.CommonCallback<T> callback) {
RequestParams params = new RequestParams(url);
if (null != map) {
for (Map.Entry<String, Object> entry : map.entrySet()) {
params.addParameter(entry.getKey(), entry.getValue());
}
}
params.setMultipart(true);
Callback.Cancelable cancelable = x.http().get(params, callback);
return cancelable;
}
/**
* 下载文件
*
* @param <T>
*/
@Override
public <T> Callback.Cancelable DownLoadFile(String url, String filepath, Callback.CommonCallback<T> callback) {
RequestParams params = new RequestParams(url);
// 设置断点续传
params.setAutoResume(true);
params.setSaveFilePath(filepath);
Callback.Cancelable cancelable = x.http().get(params, callback);
return cancelable;
}
public class JsonResponseParser implements ResponseParser {
// 检查服务器返回的响应头信息
@Override
public void checkResponse(UriRequest request) throws Throwable {
}
/**
* 转换result为resultType类型的对象
*
* @param resultType
* 返回值类型(可能带有泛型信息)
* @param resultClass
* 返回值类型
* @param result
* 字符串数据
* @return
* @throws Throwable
*/
@Override
public Object parse(Type resultType, Class<?> resultClass, String result) throws Throwable {
return new Gson().fromJson(result, resultClass);
}
}
}
3.创建一个类来返回IRequestManager请求接口的对象
/**
* Created by lvfeifie on 2016/12/11.
*/
public class RequestFactory {
public static IRequestManager getRequestManager(){
// return VolleyRequestManager.getInstance();
return XUtilsRequestManager.getInstance();
}
}
为什么要用这种方法来返回对象,而不直接在Activity/Fragment/Presenter中创建>VolleyRequestManager对象来进行操作?
如果直接在Activity/Fragment/Presenter中使用VolleyRequestManager来创建对象,你的代码就依赖了VolleyRequestManager,这种情况下,如果要更换成OkHttp,岂不是要把代码中所有的VolleyRequestManager对象也更换成OkHttp的请求对象?
再试想一下,如果你有很多个Activity/Fragment/Presenter使用了VolleyRequestManager对象,你是不是要每个地方都更换一遍?
使用RequestFactory的方式在Activity/Fragment/Presenter中创建对象,代码只依赖了IRequestManager这个接口,这就是使用接口进行解耦的关键点,无论在什么地方使用了这个接口,当要更换实现的时候,只需要修改RequestFactory中return的实现类就可以了。
4.用法
//这里发起请求依赖的是IRequestManager接口
URL = "www.baidu.com"
IRequestManager requestManager = RequestFactory.getRequestManager();
Map<String, Object> mapPost = null;
requestManager.post(URL, mapPost, new Callback.CommonCallback<String>() {
@Override
public void onSuccess(String result) {
if(result != null) {
// 保存首页数据
//this.result=result;
CacheUtils.putString(PersonalInformationActivity.this, CacheUtils.USER_INFORMATION,result);
Log.e("Login中的result,更换成功",result);
prosessDate(result);
}
}
@Override
public void onError(Throwable ex, boolean isOnCallback) {
}
@Override
public void onCancelled(CancelledException cex) {
}
@Override
public void onFinished() {
}
});
注意我们创建请求对象的代码,这里没有出现具体的实现类: IRequestManager requestManager = RequestFactory.getRequestManager();
5.想换就换
只要换的联网方法实现了第三步中的方法就行RequestFactory