1. 概述
目前市面上边比较火的第三方网络引擎会有很多,像早期的 AsyncTask、XUtils就不说了,之前的Volley、现在的Okhttp、Retrofit等等这些网络框架,我们一般在开发项目的过程中绝大部分的小伙伴可能都是只去用其中的一种,那么如果说我们后期项目需要去更换网络框架的时候,就会比较麻烦了,所以说如果有一种情况就是:只需要去在配置的基类中修改以下相关配置就可以随意切换网络框架就显得尤为重要,那么接下来我们就来看下如何实现这样的一个功能。
2. 分析
要想实现一个 可以修改配置的基类中的相关网络的代码就可以随意切换任何的网络框架,这里边是需要解决几个问题:首先是回调的问题、然后就是请求网络的问题,而我们采用的方式就是:回调我们用自己的,请求网络我们也用自己的,这样的话,这几个问题就迎刃而解了,主要就是4个类,那么下边我们就来看下具体的代码是怎样实现的。
1>:引擎规范如下:
/**
* Email: 2185134304@qq.com
* Created by JackChen 2018/4/6 12:23
* Version 1.0
* Params:
* Description: 引擎的规范
*/
public interface IHttpEngine {
// get请求
void get(Context context , String url , Map<String , Object> params , EngineCallBack callBack) ;
// post请求
void post(Context context , String url , Map<String , Object> params , EngineCallBack callBack) ;
// 上传文件
// 下载文件
// https 添加证书
}
2>:网络引擎的回调接口 EnginueCallBack代码如下:
/**
* Email: 2185134304@qq.com
* Created by JackChen 2018/4/6 12:33
* Version 1.0
* Params:
* Description: 我们自己的网络引擎的回调
*/
public interface EngineCallBack {
/**
* 网络请求成功
*/
public void onSuccess(String result) ;
/**
* 网络请求失败
*/
public void onError(Exception e) ;
/**
* 默认的,里边什么也不干
*/
public final EngineCallBack DEFAULT_CALL_BACK = new EngineCallBack() {
@Override
public void onSuccess(String result) {
}
@Override
public void onError(Exception e) {
}
} ;
}
3>:我们自己的OKHttpEngine网络代码如下:
/**
* Email: 2185134304@qq.com
* Created by JackChen 2018/4/6 12:29
* Version 1.0
* Params:
* Description: 我们自己默认的网络请求 --> OkHttpEngine
*/
public class OkHttpEngine implements IHttpEngine {
private static OkHttpClient mOkHttpClient = new OkHttpClient();
@Override
public void post(Context context, String url, Map<String, Object> params, final EngineCallBack callBack) {
final String jointUrl = HttpUtils.jointParams(url,params); //打印
Log.e("Post请求路径:",jointUrl);
// 了解 Okhhtp
RequestBody requestBody = appendBody(params);
Request request = new Request.Builder()
.url(url)
.tag(context)
.post(requestBody)
.build();
mOkHttpClient.newCall(request).enqueue(
new Callback() {
@Override
public void onFailure(okhttp3.Call call, IOException e) {
callBack.onError(e);
}
@Override
public void onResponse(okhttp3.Call call, Response response) throws IOException {
// 这个 两个回掉方法都不是在主线程中
String result = response.body().string();
Log.e("Post返回结果:",jointUrl);
callBack.onSuccess(result);
}
}
);
}
/**
* 组装post请求参数body
*/
protected RequestBody appendBody(Map<String, Object> params) {
MultipartBody.Builder builder = new MultipartBody.Builder()
.setType(MultipartBody.FORM);
addParams(builder, params);
return builder.build();
}
// 添加参数
private void addParams(MultipartBody.Builder builder, Map<String, Object> params) {
if (params != null && !params.isEmpty()) {
for (String key : params.keySet()) {
builder.addFormDataPart(key, params.get(key) + "");
Object value = params.get(key);
if (value instanceof File) {
// 处理文件 --> Object File
File file = (File) value;
builder.addFormDataPart(key, file.getName(), RequestBody
.create(MediaType.parse(guessMimeType(file
.getAbsolutePath())), file));
} else if (value instanceof List) {
// 代表提交的是 List集合
try {
List<File> listFiles = (List<File>) value;
for (int i = 0; i < listFiles.size(); i++) {
// 获取文件
File file = listFiles.get(i);
builder.addFormDataPart(key + i, file.getName(), RequestBody
.create(MediaType.parse(guessMimeType(file
.getAbsolutePath())), file));
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
builder.addFormDataPart(key, value + "");
}
}
}
}
/**
* 猜测文件类型
*/
private String guessMimeType(String path) {
FileNameMap fileNameMap = URLConnection.getFileNameMap();
String contentTypeFor = fileNameMap.getContentTypeFor(path);
if (contentTypeFor == null) {
contentTypeFor = "application/octet-stream";
}
return contentTypeFor;
}
@Override
public void get(Context context,String url, Map<String, Object> params, final EngineCallBack callBack) {
url = HttpUtils.jointParams(url, params);
Log.e("Get请求路径:", url);
Request.Builder requestBuilder = new Request.Builder().url(url).tag(context);
//可以省略,默认是GET请求
Request request = requestBuilder.build();
mOkHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
callBack.onError(e);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String resultJson = response.body().string();
callBack.onSuccess(resultJson);
Log.e("Get返回结果:", resultJson);
}
});
}
}
4>:自己实现的一套网络请求:
/**
* Email: 2185134304@qq.com
* Created by JackChen 2018/4/6 12:21
* Version 1.0
* Params:
* Description: 自己的一套实现网络请求
*/
public class HttpUtils{
// 上下文
private Context mContext ;
// 直接带参数,最好是链式调用
private String mUrl ;
// 请求方式
private int mType = GET_TYPE;
private static final int GET_TYPE = 0x0011 ;
private static final int POST_TYPE = 0x0011 ;
private Map<String , Object> mParams ;
private HttpUtils(Context context){
this.mContext = context ;
mParams = new HashMap<>() ;
}
/**
* 这里最好不要用单例,否则内存泄露,因为所有的设计模式都有自己的特定场景
*/
public static HttpUtils with(Context context){
return new HttpUtils(context) ;
}
/**
* 添加 url 路径
*/
public HttpUtils url(String url){
this.mUrl = url ;
return this ;
}
/**
* 请求的方式 --> post
* 这里为了链式调用,只需要返回this就ok
*/
public HttpUtils post(){
mType = POST_TYPE ;
return this ;
}
/**
* 请求的方式 --> get
* 这里为了链式调用,只需要返回this就ok
*/
public HttpUtils get(){
mType = GET_TYPE ;
return this ;
}
/**
* 一次添加一个参数
*/
public HttpUtils addParam(String key , Object value){
mParams.put(key , value) ;
return this ;
}
/**
* 一次添加多个参数
*/
public HttpUtils addParams(Map<String , Object> params){
mParams.putAll(params) ;
return this ;
}
/**
* 添加回调 , 最终去执行
*/
public void execute(EngineCallBack callBack){
if (callBack == null){
callBack = DEFAULT_CALL_BACK ;
}
// 判断执行方法
if (mType == POST_TYPE){
post(mUrl , mParams , callBack);
}
if (mType == GET_TYPE){
get(mUrl , mParams , callBack);
}
}
public void execute(){
execute(null);
}
// 默认是 OKHttpEngine
private static IHttpEngine mHttpEngine = new OkHttpEngine() ;
/**
* 这个是在 BaseApplication中初始化引擎的
*/
public static void init(IHttpEngine httpEngine){
mHttpEngine = httpEngine ;
}
/**
* 这个是 我们每次可以自带引擎:
* 比如每次去new Volley()、new OkHttp()、new Retrofit()等不同的引擎
*/
public static void exchange(IHttpEngine httpEngine){
}
private void get(String url, Map<String, Object> params, EngineCallBack callBack) {
mHttpEngine.get(mContext , url , params , callBack);
}
private void post(String url, Map<String, Object> params, EngineCallBack callBack) {
mHttpEngine.post(mContext , url , params , callBack);
}
/**
* 拼接参数
*/
public static String jointParams(String url, Map<String, Object> params) {
if (params == null || params.size() <= 0) {
return url;
}
StringBuffer stringBuffer = new StringBuffer(url);
if (!url.contains("?")) {
stringBuffer.append("?");
} else {
if (!url.endsWith("?")) {
stringBuffer.append("&");
}
}
for (Map.Entry<String, Object> entry : params.entrySet()) {
stringBuffer.append(entry.getKey() + "=" + entry.getValue() + "&");
}
stringBuffer.deleteCharAt(stringBuffer.length() - 1);
return stringBuffer.toString();
}
/**
* 解析一个类上面的class信息
*/
public static Class<?> analysisClazzInfo(Object object) {
Type genType = object.getClass().getGenericSuperclass();
Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
return (Class<?>) params[0];
}
}
最终只需要在MainActivity中的initData()方法中直接调用就ok
@Override
protected void initData() {
HttpUtils.with(this).url("").addParam("" , "").get().execute(new EngineCallBack() {
@Override
public void onSuccess(String result) {
Toast.makeText(MainActivity.this , "请求网络成功" , Toast.LENGTH_SHORT).show();
}
@Override
public void onError(Exception e) {
}
});
}
代码已上传至github:
https://github.com/shuai999/EssayJoke_day_09.git