Android M(6.x)使用OkHttp包解析和發(fā)送JSON請求的教程
關(guān)于Android 6.0
Android老版本網(wǎng)絡(luò)請求:
1,HttpUrlConnection
2,Apache Http Client
Android6.0版本網(wǎng)絡(luò)請求:
1,HttpUrlConnection
2,OkHttp
Android6.0版本廢棄了老的網(wǎng)絡(luò)請求,那么它的優(yōu)勢是什么呢?
1,支持SPDY,共享同一個Socket來處理同一個服務器的所有請求
2,如果SPDY不可用,則通過連接池來減少請求延時
3,無縫的支持GZIP來減少數(shù)據(jù)流量
4,緩存響應數(shù)據(jù)來減少重復的網(wǎng)絡(luò)請求
post請求發(fā)送給服務器JSON:
我們先來看一個樣例,詳細的請求發(fā)送我們下面還會講.
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);
//開啟一個線程,做聯(lián)網(wǎng)操作
new Thread() {
@Override
public void run() {
postJson();
}
}.start();
}
private void postJson() {
//申明給服務端傳遞一個json串
//創(chuàng)建一個OkHttpClient對象
OkHttpClient okHttpClient = new OkHttpClient();
//創(chuàng)建一個RequestBody(參數(shù)1:數(shù)據(jù)類型 參數(shù)2傳遞的json串)
RequestBody requestBody = RequestBody.create(JSON, json);
//創(chuàng)建一個請求對象
Request request = new Request.Builder()
.url("http://192.168.0.102:8080/TestProject/JsonServlet")
.post(requestBody)
.build();
//發(fā)送請求獲取響應
try {
Response response=okHttpClient.newCall(request).execute();
//判斷請求是否成功
if(response.isSuccessful()){\
//打印服務端返回結(jié)果
Log.i(TAG,response.body().string());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
SPDY(讀作“SPeeDY”)是Google開發(fā)的基于TCP的應用層協(xié)議,用以最小化網(wǎng)絡(luò)延遲,提升網(wǎng)絡(luò)速度,優(yōu)化用戶的網(wǎng)絡(luò)使用體驗。SPDY并不是一種用于替代HTTP的協(xié)議,而是對HTTP協(xié)議的增強。新協(xié)議的功能包括數(shù)據(jù)流的多路復用、請求優(yōu)先級以及HTTP報頭壓縮。谷歌表示,引入SPDY協(xié)議后,在實驗室測試中頁面加載速度比原先快64%。
ZIP最早由Jean-loup Gailly和Mark Adler創(chuàng)建,用于UNⅨ系統(tǒng)的文件壓縮。我們在Linux中經(jīng)常會用到后綴為.gz的文件,它們就是GZIP格式的?,F(xiàn)今已經(jīng)成為Internet 上使用非常普遍的一種數(shù)據(jù)壓縮格式,或者說一種文件格式。
HTTP協(xié)議上的GZIP編碼是一種用來改進WEB應用程序性能的技術(shù)。大流量的WEB站點常常使用GZIP壓縮技術(shù)來讓用戶感受更快的速度。這一般是指WWW服務器中安裝的一個功能,當有人來訪問這個服務器中的網(wǎng)站時,服務器中的這個功能就將網(wǎng)頁內(nèi)容壓縮后傳輸?shù)絹碓L的電腦瀏覽器中顯示出來.一般對純文本內(nèi)容可壓縮到原大小的40%.這樣傳輸就快了,效果就是你點擊網(wǎng)址后會很快的顯示出來.當然這也會增加服務器的負載. 一般服務器中都安裝有這個功能模塊的。
JSON解析
這里我們將采用json統(tǒng)一泛型解析,與一些Java的反射機制來解析泛型對象Class<?>:
1.首先我們聲明一個TypeInfo.java類用來封裝泛型相關(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泛型對象類型
private Class<?> componentType;
//Type所屬對象類型
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 對象,表示聲明此類型的類或接口。
this.rawType = (Class<?>) ((ParameterizedType) type).getRawType();
//getActualTypeArguments()返回表示此類型實際類型參數(shù)的 Type 對象的數(shù)組。
Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
this.componentType = (Class<?>) actualTypeArguments[0];
// typeReference=new TypeReference<Map<componentType,componentType>>(){};
} else if (type instanceof GenericArrayType) {
//返回 Type 對象,表示聲明此類型的類或接口。
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類 用于通過反射機制獲取泛型對象的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 編程語言中所有類型的公共高級接口。它們包括原始類型、參數(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ù)組,泛型可能有多個
Type[] args = ((ParameterizedType) type).getActualTypeArguments();
if (args != null && args.length > 0) {
return new TypeInfo(args[0]);
}
}
return null;
}
}
3.接下來重點來了,聲明一個json解析工具類ReqJsonUtils.java,主要用于通過TypeInfo相關(guā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;
}
//獲取當前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é)果對象
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 {
// 接口的返回類型如果是簡單類型,則會封裝成為一個json對象,真正的對象存儲在value屬性上
if (isPrimitiveOrWrapper(componentType)) {
result = (T) parseObject(jsonData);
} else {
//處理自定義對象
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.實現(xiàn)解析
TypeInfo typeInfo = ReqClassUtils.getCallbackGenericType(callBack.getClass()); callBack.onReqSuccess(ReqJsonUtils.parseHttpResult(typeInfo, jsonData));
2.發(fā)送請求
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請求的方法
- Android使用OkHttp發(fā)送post請求
- Android小知識之OkHttp的2種請求方式詳解
- Android Okhttp請求查詢購物車的實例代碼
- Android使用OkHttp請求自簽名的https網(wǎng)站的示例
- Android基于OkHttpUtils網(wǎng)絡(luò)請求的二次封裝
- 詳解Android中使用OkHttp發(fā)送HTTP的post請求的方法
- 詳解Android的OkHttp包編寫異步HTTP請求調(diào)用的方法
- android實現(xiàn)okHttp的get和post請求的簡單封裝與使用
相關(guān)文章
Android ExpandableListView實現(xiàn)下拉刷新和加載更多效果
這篇文章主要為大家詳細介紹了Android ExpandableListView實現(xiàn)下拉刷新和加載更多效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-06-06
Android開發(fā)實現(xiàn)的圓角按鈕、文字陰影按鈕效果示例
這篇文章主要介紹了Android開發(fā)實現(xiàn)的圓角按鈕、文字陰影按鈕效果,涉及Android界面布局與屬性設(shè)置相關(guān)操作技巧,需要的朋友可以參考下2019-04-04
Ubuntu 14.04下創(chuàng)建Genymotion安卓虛擬機的步驟詳解
Android 模擬器一直以速度奇慢無比著稱,基本慢到不可用。本文介紹我一直在用的 Genymotion,速度不亞于真機。而且功能齊全,使用簡單。下面這篇文章主要介紹了Ubuntu 14.04下創(chuàng)建Genymotion虛擬機的步驟,需要的朋友可以參考下。2017-03-03
Android開發(fā)實現(xiàn)在TextView前面加標簽示例
這篇文章主要為大家介紹了Android開發(fā)實現(xiàn)TextView前面加標簽示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-04-04
Android DrawerLayout帶有側(cè)滑功能的布局類(1)
這篇文章主要為大家詳細介紹了Android DrawerLayout帶有側(cè)滑功能的布局類,感興趣的小伙伴們可以參考一下2016-07-07
Android JNI處理圖片實現(xiàn)黑白濾鏡的方法
這篇文章主要介紹了Android JNI處理圖片實現(xiàn)黑白濾鏡的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-01-01

