上一篇咱們講到了基本的Okhttp的封裝,只須要咱們在代碼種調用okHttpUtils.getInstance().GET(url, MyCallBack),一句話完事,並且仍是鏈式的,只須要在MyCallBack中處理返回的Response便可,是否是感受很爽,不要着急,接下來會讓你更爽,請自行準備紙巾,條件容許的話也能夠爲你的寶貝充上氣。沒有看過上篇文章的,最好看一下,點擊便可跳轉: 超簡單的okhttp封裝工具類(上)。
好了,廢話很少說,進入正題,本篇主要思想是,經過上篇的封裝,聯網成功後,返回的是Response對象,咱們平時聯網須要的結果是一個JavaBean或者一個集合,泛型爲JavaBean。那麼,接下來就是實現直接返回帶泛型的集合,而不是還須要咱們處理的Response。java
首先,在MyCallBack後面加上泛型,到時候須要實例化這個callback時候,天然的把咱們須要轉換成的JavaBean以泛型的形式傳遞過去。
本篇採用Gson進行Response的json轉換,因此須要根據泛型獲取Type對象。獲取方法以下:json
//根據T獲取Type static Type getSuperclassTypeParameter(Class<?> subclass) { Type superclass = subclass.getGenericSuperclass(); if (superclass instanceof Class) { throw new RuntimeException("Missing type parameter."); } ParameterizedType parameterized = (ParameterizedType) superclass; return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]); }
咱們原來定義的MyCallBack爲接口,此時須要改寫成抽象類,由於要用到構造方法進行構造Type對象。具體代碼以下:markdown
public abstract class MyCallBack<T> { public Type mType; static Type getSuperclassTypeParameter(Class<?> subclass) { Type superclass = subclass.getGenericSuperclass(); if (superclass instanceof Class) { throw new RuntimeException("Missing type parameter."); } ParameterizedType parameterized = (ParameterizedType) superclass; return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]); } public MyCallBack() { mType = getSuperclassTypeParameter(getClass()); } public abstract void onLoadingBefore(Request request); //第二個參數爲傳入的泛型,也就是說返回的結果直接就是咱們須要的類型 public abstract void onSuccess(Response response, T result); public abstract void onFailure(Request request, Exception e); public abstract void onError(Response response); }
咱們主要是改寫Response返回的地方,也就是聯網邏輯這一塊,即requestNetWork()方法。具體請看代碼實現,註釋很清晰。網絡
private void requestNetWork(Request request, MyCallBack<Object> callBack) { /** * 處理連網邏輯,此處只處理異步操做enqueue */ callBack.onLoadingBefore(request); mOkHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { mHandler.post(() -> callBack.onFailure(request, e)); } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) { String resultStr = response.body().string(); if (callBack.mType == String.class) { // 若是想要返回字符串 直接返回就行 mHandler.post(() -> callBack.onSuccess(response, resultStr)); } else { // 須要返回解析好的javaBean集合 try { // 此處暫時寫成object,使用時返回具體的帶泛型的集合 Object obj = mGson.fromJson(resultStr, callBack.mType); mHandler.post(() -> callBack.onSuccess(response, obj)); } catch (Exception e) { // 解析錯誤時 mHandler.post(() -> callBack.onError(response)); } } } else { mHandler.post(() -> callBack.onError(response)); } } }); }
具體使用方法以下:在Fragment的OnCreatView方法中寫的邏輯,根據需求本身選擇在哪裏聯網,此處只是測試,不建議在這個方法中處理。會阻塞界面顯示。app
private String url = "http://222.133.11.150:8402/EnvService/Version/CheckVersion?imei=860806029044186&version=111"; @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { OkHttpUtils.getInstance().Get(url, new MyCallBack<ceshiBean>() { @Override public void onLoadingBefore(Request request) { } @Override public void onSuccess(Response response, ceshiBean result) { System.out.println("-----" + result.getStrApkUrl()); } @Override public void onFailure(Request request, Exception e) { } @Override public void onError(Response response) { } }); return inflater.inflate(R.layout.fragment_home,container,false); }
這是咱們根據接口寫的javaBean對象
public class ceshiBean {異步
/** * StrApkUrl : http://222.133.11.150:8402/EnvService/versioninfo/EnvDS_DZ.apk * StrUpdateDate : 2017.4.18 * StrUpdateFlag : 0 * StrUpdateLog : 1.城市空氣模塊,新增長鄉鎮站、邊界站、農村站、交通站。 * StrVersionCode : 110 * StrVersionName : 1.1.0 */ private String StrApkUrl; private String StrUpdateDate; private String StrUpdateFlag; private String StrUpdateLog; private String StrVersionCode; private String StrVersionName; public String getStrApkUrl() { return StrApkUrl; } public void setStrApkUrl(String StrApkUrl) { this.StrApkUrl = StrApkUrl; } public String getStrUpdateDate() { return StrUpdateDate; } public void setStrUpdateDate(String StrUpdateDate) { this.StrUpdateDate = StrUpdateDate; } public String getStrUpdateFlag() { return StrUpdateFlag; } public void setStrUpdateFlag(String StrUpdateFlag) { this.StrUpdateFlag = StrUpdateFlag; } public String getStrUpdateLog() { return StrUpdateLog; } public void setStrUpdateLog(String StrUpdateLog) { this.StrUpdateLog = StrUpdateLog; } public String getStrVersionCode() { return StrVersionCode; } public void setStrVersionCode(String StrVersionCode) { this.StrVersionCode = StrVersionCode; } public String getStrVersionName() { return StrVersionName; } public void setStrVersionName(String StrVersionName) { this.StrVersionName = StrVersionName; } }
到此爲止,已經實現了簡化邏輯,只須要調用方法時候傳入泛型javaBean便可,就能直接獲取數據了。ide
可能有的小夥伴會說,這只是單個javaBean對象的解析,若是咱們接口返回的是好對個javaBean的集合,怎麼辦,so easy,只須要把泛型寫成List的形式就行了,直接給你返回一個集合數據集,太爽了。工具
固然,還有更方便的寫法,你能夠再次自定義一個具體的CallBack繼承MyCallBack,實現裏面的方法,在聯網開始前顯示加載對話框,解析結束隱藏對話框,處理相應的邏輯。那麼在前臺界面只須要處理你本身的數據就能夠了。oop
聲明:本文實現思路是參考IVan的封裝思路,只作學習用途。post
public class OkHttpUtils { /** * 網絡訪問要求singleton */ private static OkHttpUtils instance; // 必需要用的okhttpclient實例,在構造器中實例化保證單一實例 private OkHttpClient mOkHttpClient; public static final MediaType JSON = MediaType. parse("application/json; charset=utf-8"); private Handler mHandler; private Gson mGson; private OkHttpUtils() { /** * okHttp3中超時方法移植到Builder中 */ mOkHttpClient = (new OkHttpClient()).newBuilder() .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(10, TimeUnit.SECONDS) .writeTimeout(30, TimeUnit.SECONDS) .build(); mHandler = new Handler(Looper.getMainLooper()); mGson = new Gson(); } public static OkHttpUtils getInstance() { if (instance == null) { synchronized (OkHttpUtils.class) { if (instance == null) { instance = new OkHttpUtils(); } } } return instance; } /** * 對外提供的Get方法訪問 * @param url * @param callBack */ public void Get(String url, MyCallBack callBack) { /** * 經過url和GET方式構建Request */ Request request = bulidRequestForGet(url); /** * 請求網絡的邏輯 */ requestNetWork(request, callBack); } /** * 對外提供的Post方法訪問 * @param url * @param parms: 提交內容爲表單數據 * @param callBack */ public void PostWithFormData(String url, Map<String, String> parms, MyCallBack callBack) { /** * 經過url和POST方式構建Request */ Request request = bulidRequestForPostByForm(url, parms); /** * 請求網絡的邏輯 */ requestNetWork(request, callBack); } /** * 對外提供的Post方法訪問 * @param url * @param json: 提交內容爲json數據 * @param callBack */ public void PostWithJson(String url, String json, MyCallBack callBack) { /** * 經過url和POST方式構建Request */ Request request = bulidRequestForPostByJson(url, json); /** * 請求網絡的邏輯 */ requestNetWork(request, callBack); } /** * POST方式構建Request {json} * @param url * @param json * @return */ private Request bulidRequestForPostByJson(String url, String json) { RequestBody body = RequestBody.create(JSON, json); return new Request.Builder() .url(url) .post(body) .build(); } /** * POST方式構建Request {Form} * @param url * @param parms * @return */ private Request bulidRequestForPostByForm(String url, Map<String, String> parms) { FormBody.Builder builder = new FormBody.Builder(); if (parms != null) { for (Map.Entry<String, String> entry : parms.entrySet()) { builder.add(entry.getKey(), entry.getValue()); } } FormBody body = builder.build(); return new Request.Builder() .url(url) .post(body) .build(); } /** * GET方式構建Request * @param url * @return */ private Request bulidRequestForGet(String url) { return new Request.Builder() .url(url) .get() .build(); } private void requestNetWork(Request request, MyCallBack<Object> callBack) { /** * 處理連網邏輯,此處只處理異步操做enqueue */ callBack.onLoadingBefore(request); mOkHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { mHandler.post(() -> callBack.onFailure(request, e)); } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) { String resultStr = response.body().string(); if (callBack.mType == String.class) { // 若是想要返回字符串 直接返回就行 mHandler.post(() -> callBack.onSuccess(response, resultStr)); } else { // 須要返回解析好的javaBean集合 try { // 此處暫時寫成object,使用時返回具體的帶泛型的集合 Object obj = mGson.fromJson(resultStr, callBack.mType); mHandler.post(() -> callBack.onSuccess(response, obj)); } catch (Exception e) { // 解析錯誤時 mHandler.post(() -> callBack.onError(response)); } } } else { mHandler.post(() -> callBack.onError(response)); } } }); } }