使用代理模式实现隔离层架构,目的是为了当出现一个新的网络框架的时候,可以在业务层无感的情况下自由切换网络库,实现热插拔,对业务层几乎没有影响。
1 架构图
以用户租房为例,租户相当于APP的业务层;一个用户会对比多套房子,所以会有多个房东,最终提供房源的是房东,所以房东就类似最终实现网络请求的网络库。
中介公司和中介属于隔离层,用户租房不直接和房东打交道,只和中介联系,至于中介和哪个房东沟通,用户无需关心,只要租到房子就行,所以中介就相当于一个中间代理。
2 类图
3 类图和架构图以及代码中的类相结合
4 代码
网络请求的结果需要回调给业务层,所以先要创建一个回调接口。
public interface ICallback {
void onSuccess(String result);
void onFailure(String error);
}
实现回调接口,把指定的的泛型JavaBean用反射的方法解析出来。然后把json转换为JavaBean回调出去。
public abstract class HttpCallback<Result> implements ICallback {
private static final String TAG = "HttpCallback";
@Override
public void onSuccess(String result) {
//获取对应的JavaBean
Class<?> clazz = parseClassInfo(this);
Result objResult = (Result) new Gson().fromJson(result, clazz);
onSuccess(objResult);
}
public abstract void onSuccess(Result objResult);
@Override
public void onFailure(String error) {
}
private Class<?> parseClassInfo(Object object) {
//获得导游泛型的父类
Type type = object.getClass().getGenericSuperclass();
Log.d(TAG, "parseClassInfo 1: "+type);
//获取参数化类型的数组
Type[] params = ((ParameterizedType) type).getActualTypeArguments();
Log.d(TAG, "parseClassInfo 2: "+params.toString());
//拿到泛型,而HttpCallback<Result>只有一个,所以取0即可得到传入的JavaBean
return (Class<?>) params[0];
}
}
然后创建一个接口主题类,也就是中介公司,中介公司只制定标准和规则,具体业务由自己公司的中介去处理。
public interface IHttpRequest {
void post(String url, Map<String, Object> params, ICallback callback);
void get(String url, ICallback callback);
}
创建代理类,也就是中介。
public class HttpHelper implements IHttpRequest {
private static HttpHelper instance;
public static HttpHelper obtain() {
synchronized (HttpHelper.class) {
if (instance == null) {
instance = new HttpHelper();
}
}
return instance;
}
private HttpHelper() {
}
private static IHttpRequest mHttpRequest;
public static void init(IHttpRequest httpRequest) {
mHttpRequest = httpRequest;
}
@Override
public void post(String url, Map<String, Object> params, ICallback callback) {
String finalUrl = appendParams(url, params);
mHttpRequest.post(finalUrl, params, callback);
}
@Override
public void get(String url, ICallback callback) {
mHttpRequest.get(url, callback);
}
public static String appendParams(String url, Map<String, Object> params) {
if (params == null || params.isEmpty()) {
return url;
}
StringBuilder urlBuilder = new StringBuilder(url);
if (urlBuilder.indexOf("?") <= 0) {
urlBuilder.append("?");
} else {
if (!urlBuilder.toString().endsWith("?")) {
urlBuilder.append("&");
}
}
for (Map.Entry<String, Object> entry : params.entrySet()) {
urlBuilder.append("&" + entry.getKey())
.append("=")
.append(encode(entry.getValue().toString()));
}
return urlBuilder.toString();
}
private static String encode(String str) {
try {
return URLEncoder.encode(str, "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw new RuntimeException();
}
}
}
创建一个类OkHttpRequest去具体实现网络请求,也就是房东,房东可以是多个,所以还可以有VolleyHttpRequest、XUtilsHttpRequest、xxxHttpRequest等。
public class OkHttpRequest implements IHttpRequest {
private OkHttpClient mOkHttpClient;
private Handler myHandler; // 此Handler是为了切换到主线程用的,处理成果
public OkHttpRequest() {
mOkHttpClient = new OkHttpClient();
myHandler = new Handler();
}
@Override
public void post(String url, Map<String, Object> params, ICallback callback) {
final RequestBody requestBody = appendBody(params);
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
mOkHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onResponse(Call call, Response response) throws IOException {
final String result = response.body().string();
if (response.isSuccessful()) {
myHandler.post(new Runnable() {
@Override
public void run() {
callback.onSuccess(result);
}
});
} else {
myHandler.post(new Runnable() {
@Override
public void run() {
callback.onFailure(result);
}
});
}
}
@Override
public void onFailure(Call call, IOException e) {
myHandler.post(new Runnable() {
@Override
public void run() {
callback.onFailure("onFailure");
}
});
}
});
}
@Override
public void get(String url, ICallback callback) {
Request request = new Request.Builder()
.url(url)
.get()
.build();
mOkHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onResponse(Call call, Response response) throws IOException {
final String result = response.body().string();
if (response.isSuccessful()) {
myHandler.post(new Runnable() {
@Override
public void run() {
callback.onSuccess(result);
}
});
} else {
myHandler.post(new Runnable() {
@Override
public void run() {
callback.onFailure(result);
}
});
}
}
@Override
public void onFailure(Call call, IOException e) {
myHandler.post(new Runnable() {
@Override
public void run() {
callback.onFailure("onFailure");
}
});
}
});
}
// 就是为了post请求的, 参数组装
private RequestBody appendBody(Map<String, Object> params) {
FormBody.Builder body = new FormBody.Builder();
if (params == null || params.isEmpty()) {
return body.build();
}
for (Map.Entry<String, Object> entry : params.entrySet()) {
body.add(entry.getKey(), entry.getValue().toString());
}
return body.build();
}
}
创建一个响应结构。
public class ResponseData {
private String result;
private String reason;
private int error_code;
private String resultcode;
public void setResult(String result) {
this.result = result;
}
public void setReason(String reason) {
this.reason = reason;
}
public void setError_code(int error_code) {
this.error_code = error_code;
}
public void setResultcode(String resultcode) {
this.resultcode = resultcode;
}
public String getResult() {
return result;
}
public String getReason() {
return reason;
}
public int getError_code() {
return error_code;
}
public String getResultcode() {
return resultcode;
}
@Override
public String toString() {
return "ResponseData{" +
"result='" + result + ''' +
", reason='" + reason + ''' +
", error_code=" + error_code +
", resultcode='" + resultcode + ''' +
'}';
}
}
初始化,指定网络请求库。
public class MainApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
//在这里切换其他HttpRequest,即可实现自由切换网络请求库。
HttpHelper.init(new OkHttpRequest());
// HttpHelper.init(new VolleyRequest(this));
// HttpHelper.init(new XUtilsRequest(this));
}
}
业务层使用。
String url = "https://www.baidu.com";
HashMap<String, Object> params = new HashMap<>();
params.put("param1", "1");
params.put("param2", "2");
HttpHelper.obtain().post(url, params, new HttpCallback<ResponseData>() {
@Override
public void onSuccess(ResponseData objResult) {
Toast.makeText(MainActivity.this, objResult.toString(), Toast.LENGTH_SHORT).show();
}
});