Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android M(6.x)使用OkHttp包解析和發送JSON請求的教程

Android M(6.x)使用OkHttp包解析和發送JSON請求的教程

編輯:關於Android編程

關於Android 6.0
Android老版本網絡請求:
1,HttpUrlConnection
2,Apache Http Client
Android6.0版本網絡請求:
1,HttpUrlConnection
2,OkHttp
Android6.0版本廢棄了老的網絡請求,那麼它的優勢是什麼呢?
1,支持SPDY,共享同一個Socket來處理同一個服務器的所有請求
2,如果SPDY不可用,則通過連接池來減少請求延時
3,無縫的支持GZIP來減少數據流量
4,緩存響應數據來減少重復的網絡請求

post請求發送給服務器JSON:

我們先來看一個樣例,詳細的請求發送我們下面還會講.

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);
 //開啟一個線程,做聯網操作
 new Thread() {
  @Override
  public void run() {

   postJson();
  }
 }.start();
}

 private void postJson() {
 //申明給服務端傳遞一個json串
 //創建一個OkHttpClient對象
 OkHttpClient okHttpClient = new OkHttpClient();
 //創建一個RequestBody(參數1:數據類型 參數2傳遞的json串)
 RequestBody requestBody = RequestBody.create(JSON, json);
 //創建一個請求對象
 Request request = new Request.Builder()
   .url("http://192.168.0.102:8080/TestProject/JsonServlet")
   .post(requestBody)
   .build();
 //發送請求獲取響應
 try {
 Response response=okHttpClient.newCall(request).execute();
  //判斷請求是否成功
  if(response.isSuccessful()){\
   //打印服務端返回結果
   Log.i(TAG,response.body().string());

  }
 } catch (IOException e) {
  e.printStackTrace();
 }

}

}

SPDY(讀作“SPeeDY”)是Google開發的基於TCP的應用層協議,用以最小化網絡延遲,提升網絡速度,優化用戶的網絡使用體驗。SPDY並不是一種用於替代HTTP的協議,而是對HTTP協議的增強。新協議的功能包括數據流的多路復用、請求優先級以及HTTP報頭壓縮。谷歌表示,引入SPDY協議後,在實驗室測試中頁面加載速度比原先快64%。
ZIP最早由Jean-loup Gailly和Mark Adler創建,用於UNⅨ系統的文件壓縮。我們在Linux中經常會用到後綴為.gz的文件,它們就是GZIP格式的。現今已經成為Internet 上使用非常普遍的一種數據壓縮格式,或者說一種文件格式。
HTTP協議上的GZIP編碼是一種用來改進WEB應用程序性能的技術。大流量的WEB站點常常使用GZIP壓縮技術來讓用戶感受更快的速度。這一般是指WWW服務器中安裝的一個功能,當有人來訪問這個服務器中的網站時,服務器中的這個功能就將網頁內容壓縮後傳輸到來訪的電腦浏覽器中顯示出來.一般對純文本內容可壓縮到原大小的40%.這樣傳輸就快了,效果就是你點擊網址後會很快的顯示出來.當然這也會增加服務器的負載. 一般服務器中都安裝有這個功能模塊的。

JSON解析
這裡我們將采用json統一泛型解析,與一些Java的反射機制來解析泛型對象Class<?>:
1.首先我們聲明一個TypeInfo.java類用來封裝泛型相關屬性

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()返回表示此類型實際類型參數的 Type 對象的數組。
   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;
   // 表示一種元素類型是參數化類型或者類型變量的數組類型
   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 編程語言中所有類型的公共高級接口。它們包括原始類型、參數化類型、數組類型、類型變量和基本類型。
  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獲取參數化類型的數組,泛型可能有多個
   Type[] args = ((ParameterizedType) type).getActualTypeArguments();
   if (args != null && args.length > 0) {
    return new TypeInfo(args[0]);
   }
  }
  return null;
 }
}

3.接下來重點來了,聲明一個json解析工具類ReqJsonUtils.java,主要用於通過TypeInfo相關屬性進行不同類型的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 {

 //基本類型映射關系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字符串轉換成指定的用戶返回值類型
  *
  * @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的數據類型
  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();
  //聲明結果對象
  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;
 }

 /**
  * 判斷是否是基本數據類型
  *
  * @param clazz
  * @return
  */
 public static boolean isPrimitiveOrWrapper(Class clazz) {
  return (clazz.isPrimitive() || isPrimitiveWrapper(clazz));
 }

 /**
  * 判斷是否是基本數據類型
  *
  * @param clazz
  * @return
  */
 public static boolean isPrimitiveWrapper(Class clazz) {
  return primitiveWrapperTypeMap.containsKey(clazz);
 }
}

如何使用?
1.實現解析

 TypeInfo typeInfo = ReqClassUtils.getCallbackGenericType(callBack.getClass());
 callBack.onReqSuccess(ReqJsonUtils.parseHttpResult(typeInfo, jsonData));

2.發送請求

  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>();//基礎類型

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved