架構師之路-網路框架的搭建(高逼格)
一,瞭解常見的框架
1,你已經工作量3年不等或也許是菜鳥,只要接觸Android開發那麼在專案中必不可少的就是一些第三方框架:常見的網路請求框架,圖片載入框架等…
我們具體瞭解下常見的網路框架:
網路框架:okhttp,Volley,Xutils,Retrofit....
圖片框架:picasso,xutils,imageLoader,glide,fresco,Fac...
他們的優點:相容性好,程式碼很少,逼格夠高,封裝….這麼多的優點,也許剛接觸開發的很多小夥子們直接拿來就在專案中使用。哪裡需要網路請求哪裡直接上程式碼也不是很費勁!如果你是這樣做的你這時候應該看完我這篇部落格啦!
二,不同級別人使用框架的方式
(1):第一種初級程式設計師:
1,初級程式設計師做法:拿來就用
2,優點:簡單粗暴
3,做法如下:
x.http().get(new RequestParams(url), new
Callback.CommonCallback<String>() {
@Override
public void onSuccess(String result) {
}
@Override
public void onError(Throwable ex, boolean isOnCallback) {
}
@Override
public void onCancelled(CancelledException cex) {
}
@Override
public void onFinished() {
}
});
4,缺點: 耦合度太高:因為一個大型專案中用到的網路框架部分有可能成千上萬,如果你是程式設計師,你所使用的網路請求框架不滿足產品的需求時候,你是要一個一個來修改麼?這麼多互動程式碼是不是很難,很耗費時間。效率極低。
(2):第二種中級程式設計師:
1,中級程式設計師做法:為了降低耦合度進行了一次封裝:
2,有點:耦合度低,小小裝逼,程式碼少了,邏輯清晰,使用方便。
3,做法如下:當然了我這裡分裝時候進行了一些簡單的操作,單例模式,泛型。相信都可以看懂。將網路框架分裝到類裡面不在跟View互動
package com.example.ls.mynetframe.volleyutils;
import android.content.Context;
import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import java.util.HashMap;
import java.util.Map;
/**
* Created by 路很長~ on 2017/7/14.
*/
public class VolleyUtils<T> {
public static VolleyUtils _instance;
private RequestQueue requestQueue;
//定義一個介面實現回掉
public interface CallBack<T> {
void onSuccess(T obj);
void onFails(String onfail);
}
private VolleyUtils(Context context) {
requestQueue = Volley.newRequestQueue(context);
}
//通過單利模式來保證只建立一個例項並且初始化Volley框架
public static VolleyUtils getInstance(Context context) {
if (_instance == null) {
synchronized (VolleyUtils.class) {
//初始化volley框架
_instance = new VolleyUtils(context);
}
}
return _instance;
}
//這裡來宣佈這個方法型別為<T>,這個編輯表示引數裡面有泛型
public <T> void getReques(String url, HashMap<String, Object> paramers, final CallBack<T> callBack) {
final StringRequest request = new StringRequest(Request.Method.GET, HttpUtilss.appendParamers(url, paramers), new Response.Listener<String>() {
@Override
public void onResponse(String response) {
// Gson gsonVolley=new Gson();
T obj = (T) response;
callBack.onSuccess(obj);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
callBack.onFails(error.toString());
}
});
requestQueue.add(request);
}
public <T> void postRequest(String url, final Map<String, String> hashMap, final CallBack<T> callBack) {
StringRequest request = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
T obj = (T) response;
callBack.onSuccess(obj);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
callBack.onFails(error.toString());
}
}) {
@Override
protected Map<String, String> getParams() throws AuthFailureError {
if (hashMap != null) {
return hashMap;
}
return super.getParams();
}
};
}
public static class HttpUtilss {
static String appendParamers(String url, HashMap<String, Object> paramers) {
StringBuffer stringBuffer = new StringBuffer();
for (HashMap.Entry<String, Object> enty : paramers.entrySet()) {
String strin = "&" + enty.getKey() + "=" + enty.getValue();
stringBuffer.append(strin);
}
return url + stringBuffer.toString();
}
}
}
4,缺點:但是這種簡單的封裝如果專案中需要維護替換網路框架,需要修改View裡面的互動程式碼,也有大量的程式碼需要在View層修改。我們如何以一個架構師的角度考慮問題,在View層我們不需要修改程式碼。只需要修改我們的網路層框架封裝類實現網路層程式碼的介面。
(3):高階架構師
1,考慮的東西:
維護,複用,可拓展,簡單實用,實用場景,開閉原則,逼格高,替換庫簡單。
2,分析圖如下:我門首先分析需求:
我們在替換框架時候需求不要動View層互動程式碼,二,只需很少的程式碼實現替換框架,我們將所有的網路請求框架程式碼放在Volley,OkHttp封裝類裡面,實現網路層封裝的介面,互動層我們也將其封裝為一個類,且實現網路層封裝的介面。替換庫時候只替換最下面的Okhttp和Volley等封裝類,只需要實現網路層裡面的介面就行。其他不用動。我們可以看到互動層和View層是沒有動的。
3,擼程式碼過程首先我們新建一個專案MyNetFrame:
第一部分:寫網路層程式碼並將其封裝在介面中:
(1.)
新建一個包okhttpframe,當然這個你們隨便自己喜好來
我們從底部網上來實現:
首先定義一個強調內容介面DataICallBack網路請求結果無非兩種成功失敗:
public interface DataICallBack {
//成功時候回撥
void onSuccess(String result);
//失敗時候回撥
void onFailure(String result);
}
(2.)
新建一個類來實現DataICallBack用來解析返回的json字串為物件,我們這個類為抽象類符合開閉原則程式碼如下:
1,在裡面使用了反射技術通過反向T,獲取需要解析的實體類型別。getType(Object obj)方法。(不知道的回顧下java基礎,這些程式碼寫多了記住最好)
2,裡面定義2個抽象方法來返回給呼叫層結果。
public abstract class FrameHttpCallback<T> implements DataICallBack {
@Override
public void onSuccess(String result) {
Gson gson = new Gson();
Type type = getType(this);
T obj = gson.fromJson(result, type);
onSuccess(obj);
}
public abstract String onSuccess(T t);
public abstract String onFail(String s);
@Override
public void onFailure(String result) {
onFail(result);
}
private static Type getType(Object obj) {
Type types = obj.getClass().getGenericSuperclass();
Type[] type_arr = ((ParameterizedType) types).getActualTypeArguments();
return type_arr[0];
}
}
(3.)將其網路層程式碼封裝起來:
便於互動層和網路請求封裝類的實現
public interface FrameHttpProcessor {
//成功:
void OnSuccess(String url, Map<String, Object> parames, FrameHttpCallback callback);
//失敗:
void OnFails(String url, Map<String, Object> parames, FrameHttpCallback callback);
}
第二部分:為了解決網路互動層和View層不會見面,我們來個代理且實現網路層介面:
(1.) 我們定義一個代理類實現網路層介面程式碼如下
public class FrameHttpHelper implements FrameHttpProcessor {
//這兒低耦合
private static FrameHttpProcessor mFrameHttpProcessor;
private static FrameHttpHelper _instance;
public FrameHttpHelper() {
}
public void init(FrameHttpProcessor processor) {
mFrameHttpProcessor = processor;
}
public static FrameHttpHelper getInstance() {
synchronized (FrameHttpHelper.class) {
if (_instance == null) {
_instance = new FrameHttpHelper();
}
return _instance;
}
}
@Override
public void get(String url, Map<String, Object> parames, FrameHttpCallback callback) {
//這裡我們進行字串的拼接
String url_result = appendParamers(url, parames);
mFrameHttpProcessor.get(url_result, parames, callback);
}
static String appendParamers(String url, Map<String, Object> paramers) {
//1.獲取最終URL方法一
/* String url_result;
url_result = url;
Set<String> keyset = paramers.keySet();
Object[] keyArray = keyset.toArray();
for (int i = 0; i < keyArray.length; i++) {
url_result += "&" + keyArray[i].toString() + "=" + paramers.get(keyArray[i].toString());
}
return url_result;*/
/**
* 2:方法二:
StringBuffer stringBuffer = new StringBuffer();
for (HashMap.Entry<String, Object> enty : paramers.entrySet()) {
String strin = "&" + enty.getKey() + "=" + enty.getValue();
stringBuffer.append(strin);
}
return url + stringBuffer.toString();**/
if (paramers == null && paramers.isEmpty()) {
return url;
}
StringBuilder urlBuider = new StringBuilder(url);
if (urlBuider.indexOf("?") <= 0) {
urlBuider.append("?");
} else {
if (!urlBuider.toString().endsWith("?")) {
urlBuider.append("&");
}
}
for (Map.Entry<String, Object> entry : paramers.entrySet()) {
urlBuider.append(entry.getKey()).append("=").append(entry.getValue().toString());
}
return urlBuider.toString();
}
@Override
public void post(String url, Map<String, Object> parames, FrameHttpCallback callback) {
//這裡我們進行字串的拼接
String url_result = appendParamers(url, parames);
mFrameHttpProcessor.get(url_result, parames, callback);
}
}
第三部分:我們正式的寫我們的Volley封裝框架類:
(1.) 我們定義一個VolleyFrameProcessor類實現FrameHttpProcessor在這個類裡面真正寫網路請求程式碼,達到隔絕View層:
public class VolleyFrameProcessor implements FrameHttpProcessor {
RequestQueue mRequstQue;
public VolleyFrameProcessor(Context context) {
mRequstQue = Volley.newRequestQueue(context);
}
@Override
public void get(String url, Map<String, Object> parames, final FrameHttpCallback callback) {
StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
callback.onSuccess(response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
callback.onFailure(error.toString());
}
});
mRequstQue.add(request);
}
@Override
public void post(String url, Map<String, Object> parames, final FrameHttpCallback callback) {
StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
callback.onSuccess(response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
callback.onFailure(error.toString());
}
});
}
}
第四部分:我們就可以拿來用了:
首先在MyApplication裡面進行註冊:
FrameHttpHelper.init(new VolleyFrameProcessor(this));
在MainActivity裡面呼叫程式碼:
HashMap<String, Object> paramss = new HashMap<>();
paramss.put("mode", "bottom_hot_boards");
paramss.put("platform", "Android");
FrameHttpHelper.getInstance().get(Config.PATH_URL,paramss,new
FrameHttpCallback<BeanJson>(){
@Override
public void onSuccess(BeanJson beanJson) {
mTv_hollo.setText(beanJson.getMsg().toString());
}
@Override
public void onFail(String s) {
Toast.makeText(MainActivity.this, "", Toast.LENGTH_LONG).show();
}
});
對了我網路接口裡面的json資料是如下
{msg='引數錯誤', result=-9109, success=false}
我調取的msg所以顯示“引數錯誤”,並不是我的引數錯了哦!你們自己找介面試試。我這個介面就這麼點東西,我懶的找了!
三,當需求來了我們需要替換框架時候:
要求把Volley框架替換為Okhttp:
具體做法如下:
1,定一個類實現FrameHttpProcessor介面:
public class OkhttpFrameProcessor implements IHttpProcessor {//實現這個介面
private OkHttpClient mOkhttClient;
private Handler mHandler;
public OkhttpFrameProcessor() {
mOkhttClient = new OkHttpClient();
mHandler = new Handler();
}
private RequestBody appendBody(Map<String, Object> paramers) {
FormBody.Builder body = new FormBody.Builder();
if (paramers == null || paramers.isEmpty()) {
return body.build();
}
for (Map.Entry<String, Object> entry : paramers.entrySet()) {
body.add(entry.getKey(), entry.getValue().toString());
}
return body.build();
}
@Override
public void get(String url, Map<String, Object> parames, final ICallback callback) {
final Request request = new Request.Builder()
.get()
.url(url)
.build();
mOkhttClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, final IOException e) {
mHandler.post(new Runnable() {
@Override
public void run() {
callback.onFailure(e.toString());
}
});
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
final String result = response.body().string();
Log.e("resutlxx", result.toString());
mHandler.post(new Runnable() {
@Override
public void run() {
callback.onSuccess(result);
}
});
} else {
mHandler.post(new Runnable() {
@Override
public void run() {
callback.onFailure("訪問失敗!");
}
});
}
}
});
}
@Override
public void post(String url, Map<String, Object> parames, final ICallback callback) {
RequestBody requestBody = appendBody(parames);
final Request request = new Request.Builder()
.url(url)
.post(requestBody)
.header("User-Agent", "a")
.build();
mOkhttClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, final IOException e) {
mHandler.post(new Runnable() {
@Override
public void run() {
callback.onFailure(e.toString());
}
});
}
@Override
public void onResponse(Call call, final Response response) throws IOException {
if (response.isSuccessful()) {
final String result = response.body().string();
mHandler.post(new Runnable() {
@Override
public void run() {
callback.onSuccess(result);
}
});
} else {
}
}
});
}
}
2,在MyApplication裡面替換為:
FrameHttpHelper.init(new OkhttpFrameProcessor());
就完事了,我們可以看到我們在View層什麼事都沒幹,只需要自己封裝框架類,實現網路層封裝介面。在MyApplication初始化就可以。
最後:高逼格架構師網路基本框架就完了,告訴你們這個框架是“三星”這樣的大佬公司使用的網路框架哦,都8點了,我要吃飯去了,下一章開始封裝圖片框架哦,希望交流討論!一起進步!