Android M(6.x)使用OkHttp包解析和發(fā)送JSON請(qǐng)求的教程
關(guān)于Android 6.0
Android老版本網(wǎng)絡(luò)請(qǐng)求:
1,HttpUrlConnection
2,Apache Http Client
Android6.0版本網(wǎng)絡(luò)請(qǐng)求:
1,HttpUrlConnection
2,OkHttp
Android6.0版本廢棄了老的網(wǎng)絡(luò)請(qǐng)求,那么它的優(yōu)勢(shì)是什么呢?
1,支持SPDY,共享同一個(gè)Socket來(lái)處理同一個(gè)服務(wù)器的所有請(qǐng)求
2,如果SPDY不可用,則通過連接池來(lái)減少請(qǐng)求延時(shí)
3,無(wú)縫的支持GZIP來(lái)減少數(shù)據(jù)流量
4,緩存響應(yīng)數(shù)據(jù)來(lái)減少重復(fù)的網(wǎng)絡(luò)請(qǐng)求
post請(qǐng)求發(fā)送給服務(wù)器JSON:
我們先來(lái)看一個(gè)樣例,詳細(xì)的請(qǐng)求發(fā)送我們下面還會(huì)講.
public class MainActivity extends AppCompatActivity { public static final String TAG = "MainActivity"; public static final MediaType JSON=MediaType.parse("application/json; charset=utf-8"); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //開啟一個(gè)線程,做聯(lián)網(wǎng)操作 new Thread() { @Override public void run() { postJson(); } }.start(); } private void postJson() { //申明給服務(wù)端傳遞一個(gè)json串 //創(chuàng)建一個(gè)OkHttpClient對(duì)象 OkHttpClient okHttpClient = new OkHttpClient(); //創(chuàng)建一個(gè)RequestBody(參數(shù)1:數(shù)據(jù)類型 參數(shù)2傳遞的json串) RequestBody requestBody = RequestBody.create(JSON, json); //創(chuàng)建一個(gè)請(qǐng)求對(duì)象 Request request = new Request.Builder() .url("http://192.168.0.102:8080/TestProject/JsonServlet") .post(requestBody) .build(); //發(fā)送請(qǐng)求獲取響應(yīng) try { Response response=okHttpClient.newCall(request).execute(); //判斷請(qǐng)求是否成功 if(response.isSuccessful()){\ //打印服務(wù)端返回結(jié)果 Log.i(TAG,response.body().string()); } } catch (IOException e) { e.printStackTrace(); } } }
SPDY(讀作“SPeeDY”)是Google開發(fā)的基于TCP的應(yīng)用層協(xié)議,用以最小化網(wǎng)絡(luò)延遲,提升網(wǎng)絡(luò)速度,優(yōu)化用戶的網(wǎng)絡(luò)使用體驗(yàn)。SPDY并不是一種用于替代HTTP的協(xié)議,而是對(duì)HTTP協(xié)議的增強(qiáng)。新協(xié)議的功能包括數(shù)據(jù)流的多路復(fù)用、請(qǐng)求優(yōu)先級(jí)以及HTTP報(bào)頭壓縮。谷歌表示,引入SPDY協(xié)議后,在實(shí)驗(yàn)室測(cè)試中頁(yè)面加載速度比原先快64%。
ZIP最早由Jean-loup Gailly和Mark Adler創(chuàng)建,用于UNⅨ系統(tǒng)的文件壓縮。我們?cè)贚inux中經(jīng)常會(huì)用到后綴為.gz的文件,它們就是GZIP格式的?,F(xiàn)今已經(jīng)成為Internet 上使用非常普遍的一種數(shù)據(jù)壓縮格式,或者說(shuō)一種文件格式。
HTTP協(xié)議上的GZIP編碼是一種用來(lái)改進(jìn)WEB應(yīng)用程序性能的技術(shù)。大流量的WEB站點(diǎn)常常使用GZIP壓縮技術(shù)來(lái)讓用戶感受更快的速度。這一般是指WWW服務(wù)器中安裝的一個(gè)功能,當(dāng)有人來(lái)訪問這個(gè)服務(wù)器中的網(wǎng)站時(shí),服務(wù)器中的這個(gè)功能就將網(wǎng)頁(yè)內(nèi)容壓縮后傳輸?shù)絹?lái)訪的電腦瀏覽器中顯示出來(lái).一般對(duì)純文本內(nèi)容可壓縮到原大小的40%.這樣傳輸就快了,效果就是你點(diǎn)擊網(wǎng)址后會(huì)很快的顯示出來(lái).當(dāng)然這也會(huì)增加服務(wù)器的負(fù)載. 一般服務(wù)器中都安裝有這個(gè)功能模塊的。
JSON解析
這里我們將采用json統(tǒng)一泛型解析,與一些Java的反射機(jī)制來(lái)解析泛型對(duì)象Class<?>:
1.首先我們聲明一個(gè)TypeInfo.java類用來(lái)封裝泛型相關(guān)屬性
import java.lang.reflect.Array; import java.lang.reflect.GenericArrayType; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; public class TypeInfo { //Type泛型對(duì)象類型 private Class<?> componentType; //Type所屬對(duì)象類型 private Class<?> rawType; //type private Type type; private TypeInfo(Class<?> rawType, Class<?> componentType) { this.componentType = componentType; this.rawType = rawType; } public static TypeInfo createArrayType(Class<?> componentType) { return new TypeInfo(Array.class, componentType); } public static TypeInfo createNormalType(Class<?> componentType) { return new TypeInfo(null, componentType); } public static TypeInfo createParameterizedType(Class<?> rawType, Class<?> componentType) { return new TypeInfo(rawType, componentType); } public TypeInfo(Type type) { this.type = type; if (type instanceof ParameterizedType) { //返回 Type 對(duì)象,表示聲明此類型的類或接口。 this.rawType = (Class<?>) ((ParameterizedType) type).getRawType(); //getActualTypeArguments()返回表示此類型實(shí)際類型參數(shù)的 Type 對(duì)象的數(shù)組。 Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments(); this.componentType = (Class<?>) actualTypeArguments[0]; // typeReference=new TypeReference<Map<componentType,componentType>>(){}; } else if (type instanceof GenericArrayType) { //返回 Type 對(duì)象,表示聲明此類型的類或接口。 this.rawType = Array.class; // 表示一種元素類型是參數(shù)化類型或者類型變量的數(shù)組類型 this.componentType = (Class<?>) ((GenericArrayType) type).getGenericComponentType(); } else { this.componentType = (Class<?>) type; } } public Type getType() { return type; } public Class<?> getComponentType() { return componentType; } public Class<?> getRawType() { return rawType; } }
2.聲明ReqClassUtils.java類 用于通過反射機(jī)制獲取泛型對(duì)象的TypeInfo
import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; public class ReqClassUtils { public static TypeInfo getCallbackGenericType(Class<?> clazz) { //獲得帶有泛型的父類 Type genericSuperclass = clazz.getGenericSuperclass();//Type是 Java 編程語(yǔ)言中所有類型的公共高級(jí)接口。它們包括原始類型、參數(shù)化類型、數(shù)組類型、類型變量和基本類型。 TypeInfo type = getGetnericType(genericSuperclass); if (type == null) { Type[] genericInterfaces = clazz.getGenericInterfaces(); if (genericInterfaces != null && genericInterfaces.length > 0) { type = getGetnericType(genericInterfaces[0]); } } return type; } private static TypeInfo getGetnericType(Type type) { if (type != null && type instanceof ParameterizedType) { //getActualTypeArguments獲取參數(shù)化類型的數(shù)組,泛型可能有多個(gè) Type[] args = ((ParameterizedType) type).getActualTypeArguments(); if (args != null && args.length > 0) { return new TypeInfo(args[0]); } } return null; } }
3.接下來(lái)重點(diǎn)來(lái)了,聲明一個(gè)json解析工具類ReqJsonUtils.java,主要用于通過TypeInfo相關(guān)屬性進(jìn)行不同類型的json解析
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONException; import com.alibaba.fastjson.JSONObject; import java.lang.reflect.Array; import java.util.Collection; import java.util.HashMap; import java.util.Map; import static com.alibaba.fastjson.JSON.parseObject; public class ReqJsonUtils { //基本類型映射關(guān)系Map private static final Map primitiveWrapperTypeMap = new HashMap(8); static { //添加基本類型 primitiveWrapperTypeMap.put(Boolean.class, boolean.class); primitiveWrapperTypeMap.put(Byte.class, byte.class); primitiveWrapperTypeMap.put(Character.class, char.class); primitiveWrapperTypeMap.put(Double.class, double.class); primitiveWrapperTypeMap.put(Float.class, float.class); primitiveWrapperTypeMap.put(Integer.class, int.class); primitiveWrapperTypeMap.put(Long.class, long.class); primitiveWrapperTypeMap.put(Short.class, short.class); } /** * 將JSON字符串轉(zhuǎn)換成指定的用戶返回值類型 * * @param type * @param jsonData * @return * @throws JSONException */ public static <T> T parseHttpResult(TypeInfo type, String jsonData) throws JSONException { // 處理Void類型的返回值 if (Void.class.isAssignableFrom(type.getComponentType())) { return null; } //獲取當(dāng)前type的數(shù)據(jù)類型 Class<?> rawType = type.getRawType(); //是否是Array boolean isArray = rawType != null && Array.class.isAssignableFrom(rawType); //是否是Collection boolean isCollection = rawType != null && Collection.class.isAssignableFrom(rawType); //是否是Map boolean isMap = rawType != null && Map.class.isAssignableFrom(rawType); //獲取泛型類型 Class<?> componentType = type.getComponentType(); //聲明結(jié)果對(duì)象 T result = null; if (isCollection) {//處理collection result = (T) JSON.parseArray(jsonData, componentType); } else if (isArray) {//處理array result = (T) JSON.parseArray(jsonData, componentType).toArray(); } else if (isMap) {//處理Map result = (T) JSONObject.parseObject(jsonData, type.getType()); } else if (componentType.isAssignableFrom(String.class)) {//處理字符串返回值 return (T) jsonData; } else { // 接口的返回類型如果是簡(jiǎn)單類型,則會(huì)封裝成為一個(gè)json對(duì)象,真正的對(duì)象存儲(chǔ)在value屬性上 if (isPrimitiveOrWrapper(componentType)) { result = (T) parseObject(jsonData); } else { //處理自定義對(duì)象 result = (T) parseObject(jsonData, componentType); } } return result; } /** * 判斷是否是基本數(shù)據(jù)類型 * * @param clazz * @return */ public static boolean isPrimitiveOrWrapper(Class clazz) { return (clazz.isPrimitive() || isPrimitiveWrapper(clazz)); } /** * 判斷是否是基本數(shù)據(jù)類型 * * @param clazz * @return */ public static boolean isPrimitiveWrapper(Class clazz) { return primitiveWrapperTypeMap.containsKey(clazz); } }
如何使用?
1.實(shí)現(xiàn)解析
TypeInfo typeInfo = ReqClassUtils.getCallbackGenericType(callBack.getClass()); callBack.onReqSuccess(ReqJsonUtils.parseHttpResult(typeInfo, jsonData));
2.發(fā)送請(qǐng)求
HashMap<String, String> paramsMap = new HashMap<>(); paramsMap.put("sourceType", "2"); paramsMap.put("sourceDesc", "[Android]" + Build.VERSION.RELEASE + "[Mobel]" + Build.BRAND + " " + Build.MODEL + Build.DEVICE); HashMap<String, String> params = dealStringBody(paramsMap); RequestManager.getInstance(this).requestAsyn("xxx/actionUrl", RequestManager.TYPE_POST_JSON, params, new ReqCallBack<String>() { @Override public void onReqSuccess(String result) { request_tv.setText(result); } @Override public void onReqFailed(String errorMsg) { } });
3.支持類型
new ReqCallBack<List<Object>>();//集合collection new ReqCallBack<Map<String, User>>();//map new ReqCallBack<Void>();//Void new ReqCallBack<Long>();//基礎(chǔ)類型
- Android中使用OkHttp包處理HTTP的get和post請(qǐng)求的方法
- Android使用OkHttp發(fā)送post請(qǐng)求
- Android小知識(shí)之OkHttp的2種請(qǐng)求方式詳解
- Android Okhttp請(qǐng)求查詢購(gòu)物車的實(shí)例代碼
- Android使用OkHttp請(qǐng)求自簽名的https網(wǎng)站的示例
- Android基于OkHttpUtils網(wǎng)絡(luò)請(qǐng)求的二次封裝
- 詳解Android中使用OkHttp發(fā)送HTTP的post請(qǐng)求的方法
- 詳解Android的OkHttp包編寫異步HTTP請(qǐng)求調(diào)用的方法
- android實(shí)現(xiàn)okHttp的get和post請(qǐng)求的簡(jiǎn)單封裝與使用
相關(guān)文章
Android自定義ViewGroup實(shí)現(xiàn)選擇面板
ViewGroup是上面提到的所有的父控件的父類;但ViewGroup是一個(gè)抽象類,它里面有一個(gè)抽象方法onLayout,這個(gè)方法的作用就是擺放它所有的子控件(安排位置),因?yàn)槭浅橄箢悾荒苤苯觧ew對(duì)象,所以我們?cè)诓季治募胁荒苤苯邮褂?nbsp;ViewGroup2022-07-07Android帶圓形數(shù)字進(jìn)度的自定義進(jìn)度條示例
本篇文章主要介紹了Android帶圓形數(shù)字進(jìn)度的自定義進(jìn)度條示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧2017-02-02Android Studio導(dǎo)入Eclipse項(xiàng)目時(shí).so庫(kù)文件的解決方法
這篇文章主要介紹了Android Studio導(dǎo)入Eclipse項(xiàng)目時(shí)項(xiàng)目中".so"庫(kù)文件的解決方法,需要的朋友可以參考下2018-06-06Android Studio 3.1.3升級(jí)至3.6.1后舊項(xiàng)目的兼容操作方法
這篇文章主要介紹了Android Studio 3.1.3升級(jí)至3.6.1后舊項(xiàng)目的兼容操作方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03Android自定義ProgressBar實(shí)現(xiàn)漂亮的進(jìn)度提示框
這篇文章主要為大家詳細(xì)介紹了Android自定義ProgressBar實(shí)現(xiàn)漂亮的進(jìn)度提示框,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06Android BLE 藍(lán)牙開發(fā)之實(shí)現(xiàn)掃碼槍基于BLESSED開發(fā)
這篇文章主要介紹了Android BLE 藍(lán)牙開發(fā)之實(shí)現(xiàn)掃碼槍基于BLESSED開發(fā),示例代碼介紹了第三方庫(kù)BLESSED for Android的使用,需要的朋友可以參考下2022-03-03Android基于AudioManager、PhoneStateListener實(shí)現(xiàn)設(shè)置黑名單功能
這篇文章主要介紹了Android基于AudioManager、PhoneStateListener實(shí)現(xiàn)設(shè)置黑名單功能的方法,涉及Android操作手機(jī)通信錄及通話模式與手機(jī)狀態(tài)的相關(guān)技巧,需要的朋友可以參考下2016-01-01Android?studio?利用共享存儲(chǔ)進(jìn)行用戶的注冊(cè)和登錄驗(yàn)證功能
這篇文章主要介紹了Android?studio?利用共享存儲(chǔ)進(jìn)行用戶的注冊(cè)和登錄驗(yàn)證功能,包括注冊(cè)頁(yè)面布局及登錄頁(yè)面功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2021-12-12GridView實(shí)現(xiàn)桌面圖標(biāo)顯示案例
這篇文章主要為大家詳細(xì)介紹了GridView實(shí)現(xiàn)桌面圖標(biāo)顯示案例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08Android 改變圖標(biāo)原有顏色和搜索框的實(shí)例代碼
讓Android也能有iOS那么方便的圖片色調(diào)轉(zhuǎn)換,就像同一個(gè)圖標(biāo),但是有多個(gè)地方使用,并且顏色不一樣,就可以用這個(gè)方法了。 本文實(shí)現(xiàn)TextView圖片和文字居中,鍵盤搜索功能,具體實(shí)現(xiàn)代碼大家跟隨腳本之家小編看看吧2017-09-09