由于技术的更新发展,新技术新框架层出不穷。如果代码没有重构或者重构的不好,会造成很多问题,比如项目中某个框架过时不能用了,如果没有重构,在项目中每个用过该框架的地方都要一一修改,如果项目小还好,如果项目很大,那改动起来工作量会很大。怎么让自己项目不因框架的更新而发生改动,或者改动很小?这就需要代码重构了。怎么进行代码重构?下面以网络框架为例,进行代码重构。
首先,在项目-app下build.gradle下添加依赖:
implementation 'com.android.volley:volley:1.1.0'
implementation 'com.google.code.gson:gson:2.2.4'
implementation 'com.squareup.okhttp3:okhttp:3.4.1'
创建接口IHttpProcessor:
public interface IHttpProcessor {
//该类相当于房地产公司,拥有卖房能力(对应网络请求,具有访问网络能力)
void post(String url, Map params,ICallback callback);
}
创建接口ICallback:
public interface ICallback {
void onSuccess(String result);
void onFailure();
}
创建HttpCallback继承ICallback :
public abstract class HttpCallback implements ICallback {
//将网络访问框架得到的数据转为json对象,再转换为实体对象
@Override
public void onSuccess(String result) {
Gson gson = new Gson();
Class> claz = analysisClassInfo(this);
Result o = (Result) gson.fromJson(result,claz);
onSuccess(o);
}
private Class> analysisClassInfo(Object object) {
//得到HttpCallback后的泛型
Type genType = object.getClass().getGenericSuperclass();
Type[] actualTypeArguments = ((ParameterizedType) genType).getActualTypeArguments();
return (Class>)actualTypeArguments[0];
}
public abstract void onSuccess(Result objResult);
@Override
public void onFailure() {
}
}
创建HttpHelper:
public class HttpHelper {
private static HttpHelper instance;
private HttpHelper(){}
public static HttpHelper getInstance(){
if(instance==null){
synchronized (HttpHelper.class){
if(instance==null) {
instance=new HttpHelper();
}
}
}
return instance;
}
//需要持有一个有房的人,相当于持有某个第三方网络框架
private static IHttpProcessor mHttpProcessor;
public static void init(IHttpProcessor httpProcessor){
mHttpProcessor=httpProcessor;
}
public void post(String url, Map params,ICallback callback){
//调用具体的第三方的post
String pjurl=appendParams(url,params);
mHttpProcessor.post(pjurl,params,callback);
}
private String appendParams(String url,Map 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 entry : params.entrySet()){
urlBuilder.append("&"+entry.getKey()).append("=").append(enencode(entry.getValue().toString()));
}
return urlBuilder.toString();
}
private String enencode(String toString) {
try {
return URLEncoder.encode(toString,"utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw new RuntimeException("encode fail");
}
}
}
如果使用的是volley框架,那么创建VolleyProcessor继承IHttpProcessor:
public class VolleyProcessor implements IHttpProcessor {
private static RequestQueue mQueue = null;
public VolleyProcessor(Context context){
mQueue = Volley.newRequestQueue(context);
}
@Override
public void post(String url, Map params, ICallback callback) {
StringRequest stringRequest = new StringRequest(Request.Method.POST, url, new Response.Listener() {
@Override
public void onResponse(String response) {
callback.onSuccess(response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
mQueue.add(stringRequest);
}
}
如果使用的是OKhttp框架,那么创建OkhttpProcessor继承IHttpProcessor:
public class OkhttpProcessor implements IHttpProcessor {
private OkHttpClient mOkHttpClient;
private Handler myHandler;
public OkhttpProcessor(){
mOkHttpClient= new OkHttpClient();
myHandler = new Handler();
}
@Override
public void post(String url, Map params, ICallback callback) {
RequestBody requestBody = appendBody(params);
Request request = new Request.Builder().url(url).post(requestBody).build();
mOkHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if(response.isSuccessful()) {
String str = response.body().string();
myHandler.post(new Runnable() {
@Override
public void run() {
callback.onSuccess(str);
}
});
}
}
});
}
private RequestBody appendBody(Map params) {
FormBody.Builder body = new FormBody.Builder();
if(params == null || params.isEmpty()) {
return body.build();
}
for (Map.Entry entry : params.entrySet()){
body.add(entry.getKey(),entry.getValue().toString());
}
return body.build();
}
}
创建MyApplication继承Application,在onCreate方法内初始化要使用的框架,并在AndroidManifest.xml中的application中添加
android:name=".MyApplication":
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
// HttpHelper.init(new VolleyProcessor(this));
HttpHelper.init(new OkhttpProcessor());
}
}
如果要更换框架,在application中进行切换即可。
在网络框架调用页面调用封装后的框架,这里以MainActivity为例:
public class MainActivity extends AppCompatActivity {
private String url="http://v.juhe.cn/historyWeather/citys";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Map params = new HashMap<>();
params.put("province_id",1);
params.put("key","bb52107206585ab074f5e59a8c73875b");
HttpHelper.getInstance().post(url, params, new HttpCallback() {
@Override
public void onSuccess(ResponseBean objResult) {
Log.e("===",objResult.toString());
}
});
}
}
这样在框架调用页面就不会出现具体的某个框架,而是使用重构后的代码。如果框架改动,只需要改动少部分的代码即可,工作量大为减少。
例子中的url="http://v.juhe.cn/historyWeather/citys?province_id=1&key=bb52107206585ab074f5e59a8c73875b"返回的json数据为:
{"resultcode":"112","reason":"当前可请求的次数不足","result":null,"error_code":10012}
根据json结构创建bean对象ResponseBean:
public class ResponseBean {
private String reason;
private int resultCode;
public ResponseBean() {
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
public int getResultCode() {
return resultCode;
}
public void setResultCode(int resultCode) {
this.resultCode = resultCode;
}
@Override
public String toString() {
return "ResponseBean{" +
"reason='" + reason + '\'' +
", resultCode=" + resultCode +
'}';
}
}
经测试,可以很便捷的切换框架。
源码下载