淺析Android整合OKHttp與Gson實例
Json 介紹
JsonObject 對應Json字符串中用{}包裹的數(shù)據(jù),相當于一個實體類
JsonArray對應Json字符串中用[]包裹的數(shù)據(jù),相當于一個數(shù)組
下面為從某個服務器中拉去的數(shù)據(jù),其中data為數(shù)據(jù)核心部分,minfo為一個數(shù)組,其中包含所需要渲染的數(shù)據(jù),filter為一個數(shù)據(jù)實體,包含篩選條件信息。
{ "status":"200", "msg ":"success", "source":"156", "data":{ "data_type":"2", "minfo":Array[30], "filter":{ "orderby":[ { "title":"Popular", "id":"1" }, Object{...}, Object{...} ], "genre":Array[27], "pub":Array[12], "type":Array[3], "country":Array[49] } } }
創(chuàng)建對應格式化實體類
從服務器端拉去的Json字符串,需要創(chuàng)建對應的實體類進行接收,本文介紹一種插件,用于Android端格式化建立實體類
安裝插件GsonFormatPlus
點擊設置->plugins->搜索并安裝插件GsonFormatPlus插件
創(chuàng)建實體類
第一步,在需要創(chuàng)建實體類的地方右擊空白處,在彈出的顯示框中選擇Generate
第二步,然后在選擇剛才安裝的插件GsonFormatPlus
第三步,最后將Json字符串復制上去,點擊OK即可自動創(chuàng)建
踩坑筆記
如果你不想一次性創(chuàng)建所有的Json數(shù)據(jù)對于的實體類,也就是說,你所請求的Json字符串你不想創(chuàng)建在一個實體類中,比如下面Json字符串為例,下面的minfo是一個數(shù)組,如果你想把這個數(shù)組內(nèi)的數(shù)據(jù)單獨建立一個實體類,你需要把這個字段定義為JsonArray類型,注意不是全大寫,全大寫是另外一個類,會出錯,JsonObject同理。這樣可以讓數(shù)據(jù)更加層次分明,在不同的地方引用時,較為方便。
private JsonArray orderby;
{ "status":"200", "msg ":"success", "source":"156", "data":{ "data_type":"2", "minfo":Array[30], "filter":{ "orderby":[ { "title":"Popular", "id":"1" }, Object{...}, Object{...} ], "genre":Array[27], "pub":Array[12], "type":Array[3], "country":Array[49] } } }
Json數(shù)據(jù)解析
引入依賴
implementation 'com.squareup.okhttp3:okhttp:3.1.0'
implementation 'com.squareup.okio:okio:1.5.0'
implementation 'com.google.code.gson:gson:2.8.0'
OkHttp封裝
將請求體用map進行鍵值對進行添加,然后使用表單進行提交。在建立Request對象將請求體進行上傳,然后在newCall中接受服務器回調(diào),此類是一個封裝類,只取出第一層數(shù)據(jù)體,因為不同的接口所返回的數(shù)據(jù)內(nèi)容不一樣,Json體也不一樣,所有此處只對第一層進行解析,然后在不同的地方調(diào)用時,在進行具體解析。
/** * @param url connect server address * @param map request param * @param callback bind success or fail callback*/ public void Post(String url,Map<String,Object> map,HttpCallback callback) { OkHttpClient client = new OkHttpClient(); FormBody.Builder requestBuild = new FormBody.Builder(); for (Map.Entry<String,Object> mEntry : map.entrySet()) { requestBuild.add(mEntry.getKey(),mEntry.getValue()+""); } RequestBody requestBody = requestBuild.build(); Request request = new Request.Builder() .url(url) .post(requestBody) .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { Log.e("getInternetData","error message = "+e.getMessage()); callback.onFailure(ErrorParam.POSTINGERROR); } @Override public void onResponse(Call call, Response response) throws IOException { String body = response.body().string(); int code = response.code(); if (code == 200){ try { JSONObject jsonObject = new JSONObject(body); int status_code = jsonObject.getInt("status"); if (status_code == 200){ String data = jsonObject.getString("data"); callback.onResponse(data); }else { callback.onFailure(ErrorParam.NETWORKERROR);//net error } } catch (JSONException e) { Log.e("getBannerData","error"); callback.onFailure(ErrorParam.RESOLVINGERROR);//resolve error e.printStackTrace(); } }else { callback.onFailure(ErrorParam.SERVERERROR);//service error } } }); }
JsonObject解析
* resolve jsonboject*/ public static <T> T fromJson(String josn,Class<T> c){ Gson gson = new Gson(); T t = null; return t = gson.fromJson(josn,c); }
JsonArray解析
public static <T> List<T> fromListJson(String json,Class<T> c){ List<T> list = new ArrayList<>(); Gson gson = new Gson(); JsonArray array = new JsonParser().parse(json).getAsJsonArray(); for (final JsonElement element: array) { list.add(gson.fromJson(element,c)); } return list; }
回調(diào)
建立一個回調(diào)接口,將解析結果暴露給外部
public interface HttpCallback<T> { void onFailure(int error); void onResponse(T data) throws JSONException; }
完整封裝
因為隱私,服務器接口和請求體暫不外露,其余內(nèi)容如下所示
public class OKHttpUtils { private static Map<String,Object> map = new HashMap<>(); private static OKHttpUtils singleton; private OKHttpUtils(){ } public static OKHttpUtils getInstance(){ if (singleton == null){ Sync(); } return singleton; } private static synchronized void Sync(){ if (singleton == null){ singleton = new OKHttpUtils(); InitMap(); } } /** * @param url connect server address * @param map request param * @param callback bind success or fail callback*/ public void Post(String url,Map<String,Object> map,HttpCallback callback) { OkHttpClient client = new OkHttpClient(); FormBody.Builder requestBuild = new FormBody.Builder(); for (Map.Entry<String,Object> mEntry : map.entrySet()) { requestBuild.add(mEntry.getKey(),mEntry.getValue()+""); } RequestBody requestBody = requestBuild.build(); Request request = new Request.Builder() .url(url) .post(requestBody) .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { Log.e("getInternetData","error message = "+e.getMessage()); callback.onFailure(ErrorParam.POSTINGERROR); } @Override public void onResponse(Call call, Response response) throws IOException { String body = response.body().string(); Log.d("sss",body.toString()); int code = response.code(); if (code == 200){ try { JSONObject jsonObject = new JSONObject(body); int status_code = jsonObject.getInt("status"); if (status_code == 200){ String data = jsonObject.getString("data"); callback.onResponse(data); }else { callback.onFailure(ErrorParam.NETWORKERROR);//net error } } catch (JSONException e) { Log.e("getBannerData","error"); callback.onFailure(ErrorParam.RESOLVINGERROR);//resolve error e.printStackTrace(); } }else { callback.onFailure(ErrorParam.SERVERERROR);//service error } } }); } /** * public request param*/ private static void InitMap(){ //因為隱私,請求體省略 } public Map<String,Object> getMap(){ return map; } public String setUrl(String port){ return PortParam.BaseUrl+port; } /** * resolve jsonboject*/ public static <T> T fromJson(String josn,Class<T> c){ Gson gson = new Gson(); T t = null; return t = gson.fromJson(josn,c); } /** * resolve jsonarray*/ public static <T> List<T> fromListJson(String json,Class<T> c){ List<T> list = new ArrayList<>(); Gson gson = new Gson(); JsonArray array = new JsonParser().parse(json).getAsJsonArray(); for (final JsonElement element: array) { list.add(gson.fromJson(element,c)); } return list; } }
Json解析
然后在外部進行服務器地址、請求體上傳,在進行進一步解析,在下面通過剛剛建立的回調(diào)接口,在OnFailure()中進行錯誤解析回調(diào),并處理;在OnResponse()中進行json字符串獲取,此字符串已經(jīng)被解析了一層,在根據(jù)不同的接口回調(diào),做出不同響應即可,此處將獲取的json字符串轉為數(shù)組形式。
private void Post(){ OKHttpUtils utils = OKHttpUtils.getInstance(); Map<String,Object> map = utils.getMap(); //內(nèi)容省略...map.put("",""); utils.Post(utils.setUrl(PortParam.TvShowsPort), map, new HttpCallback() { @Override public void onFailure(int error) { switch (error){ case ErrorParam.NETWORKERROR: break; case ErrorParam.SERVERERROR: break; case ErrorParam.RESOLVINGERROR: break; case ErrorParam.POSTINGERROR: handler.sendEmptyMessage(4); break; } } @Override public void onResponse(Object data) throws JSONException { array = new JSONArray(data.toString()); handler.sendEmptyMessage(0); } }); }
然后使用rxjava進行監(jiān)聽,此框架一目了然,subscribe()建立被觀察者,subscribe()建立觀察者,然后onNext()、onComplete(),此處回調(diào)的數(shù)據(jù)較多,又分為不同的場景,頭部有一個輪播圖baner數(shù)據(jù),下面有一個RecyclerView嵌套RecyclerView,需要根據(jù)判斷解析的Display_type
判斷其顯示方式,從而決定RecyclerView是橫向顯示還是豎向顯示。最后通過handler異步渲染UI。
private void UpdateUI(){ Observable.create(new ObservableOnSubscribe<FeaturedData>() { @Override public void subscribe(@NotNull ObservableEmitter<FeaturedData> observableEmitter) throws Exception { if (featuredDataList != null){ for (int i = 0; i < featuredDataList.size(); i++) { if (featuredDataList.get(i).getData_type().equals("1")){ observableEmitter.onNext(featuredDataList.get(i)); } } observableEmitter.onComplete(); } } }).subscribe(new Observer<FeaturedData>() { @Override public void onSubscribe(@NotNull Disposable disposable) { } @Override public void onNext(@NotNull FeaturedData featuredData) { if (featuredData.getName().equals("Banner")){ try { JSONArray array = new JSONArray(featuredData.getData().toString()); featureBannerDataList = OKHttpUtils.fromListJson(array.toString(),FeatureBannerData.class); //update banner handler.sendEmptyMessage(2); } catch (JSONException e) { e.printStackTrace(); } }else if (featuredData.getDisplay_type().equals("1")){ //v JSONArray jsonArray = null; JSONObject object = null; try { jsonArray = new JSONArray(featuredData.getData().toString()); object = jsonArray.getJSONObject(0); } catch (JSONException e) { e.printStackTrace(); } FeatureInnerData data = OKHttpUtils.fromJson(object.toString(),FeatureInnerData.class); data.setSlide_way(1); featureInnerDataList.add(data); }else { //H JSONArray jsonArray = null; JSONObject object = null; try { jsonArray = new JSONArray(featuredData.getData().toString()); object = jsonArray.getJSONObject(0); } catch (JSONException e) { e.printStackTrace(); } FeatureInnerData data = OKHttpUtils.fromJson(object.toString(),FeatureInnerData.class); data.setSlide_way(2); featureInnerDataList.add(data); } } @Override public void onError(@NotNull Throwable throwable) { } @Override public void onComplete() { handler.sendEmptyMessage(3); } }); }
到此這篇關于淺析Android整合OKHttp與Gson實例的文章就介紹到這了,更多相關Android OKHttp Gson內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Android自定義控件實現(xiàn)帶文本與數(shù)字的圓形進度條
這篇文章主要為大家詳細介紹了Android自定義控件實現(xiàn)帶文本與數(shù)字的圓形進度條,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-12-12Android編程實現(xiàn)自定義ImageView圓圖功能的方法
這篇文章主要介紹了Android編程實現(xiàn)自定義ImageView圓圖功能的方法,結合實例形式分析了Android自定義ImageView及實現(xiàn)圓圖效果的具體步驟與相關操作技巧,需要的朋友可以參考下2017-08-08實現(xiàn)輪轉廣告帶底部指示的自定義ViewPager控件
在項目中經(jīng)常需要使用輪轉廣告的效果,在android-v4版本中提供的ViewPager是一個很好的工具,而一般我們使用Viewpager的時候,都會選擇在底部有一排指示物指示當前顯示的是哪一個page,下面我們就做這個功能的實現(xiàn)2013-11-11