文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2022-06-06 08:11

关注

关于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);
 }
 
 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;
 }
 
 public static boolean isPrimitiveOrWrapper(Class clazz) {
  return (clazz.isPrimitive() || isPrimitiveWrapper(clazz));
 }
 
 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>();//基础类型
您可能感兴趣的文章:详解Android中使用OkHttp发送HTTP的post请求的方法Android中使用OkHttp包处理HTTP的get和post请求的方法详解Android的OkHttp包编写异步HTTP请求调用的方法Android基于OkHttpUtils网络请求的二次封装Android使用OkHttp请求自签名的https网站的示例Android Okhttp请求查询购物车的实例代码Android中okhttp3使用详解Android OkHttp的简单使用和封装详解Android小知识之OkHttp的2种请求方式详解


阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-移动开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯