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

关于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>();//基础类型
(0)

相关推荐

  • 详解http访问解析流程原理

    详解http访问解析流程原理 http访问网址域名解析流程: 1.在浏览器中输入www.qq.com域名,操作系统会先检查自己本地的hosts文件是否有这个网址映射关系,如果有,就先调用这个IP地址映射,完成域名解析. 2.如果hosts里没有这个域名的映射,则查找本地DNS解析器缓存,是否有这个网址映射关系,如果有,直接返回,完成域名解析. 3.如果hosts与本地DNS解析器缓存都没有相应的网址映射关系,首先会找TCP/ip参数中设置的首选DNS服务器,在此我们叫它本地DNS服务器,此服务器

  • 激动人心的 Angular HttpClient的源码解析

    Angular 4.3.0-rc.0版本已经发布

  • 深入解析nodejs HTTP服务

    我最近在研究nodejs的路上,正好这两天了解了nodejs HTTP服务,那么今天也算个学习笔记吧! nodejs最重要的方面之一是具有非常迅速的实现HTTP和HTTPS服务器和服务的能力.http服务是相当低层次的,你可能要用到不同的模块,如express来实现完整的Web服务器,http模块不提供处理路由.cookie.缓存等的调用.我们主要用http模块的地方是实现供应用程序使用的后端Web服务.  1.处理URL 统一资源定位符(URL)为把一个请求发到正确的服务器的特定端口上,并访问

  • HTTPS混合内容解析附解决方法

    什么是HTTPS混合内容 我们可能会有这样的经验,当我们通过HTTPS访问一个网站的时候,突然有提示:"本页面包含有不安全的内容".这个时候会询问是否显示"不安全的内容",这个时候,就是遇到了有混合内容的页面了. HTTPS下的页面,几乎很少是采用单一连接,HTML标识.图片.JS脚本以及其他页面资源不仅是多个连接获取到,甚至可能是来自完全不同的服务器和网站.为了确保一个页面进行了正确的加密,所有的页面资源都通过HTTPS进去获取是必要的.但在实际情况中,全部资源都

  • 解析ajax核心XMLHTTPRequest对象的创建与浏览器的兼容问题

    MLHttpRequest 对象是AJAX功能的核心,要开发AJAX程序必须从了解XMLHttpRequest 对象开始. 了解XMLHttpRequest 对象就先从创建XMLHttpRequest 对象开始,在不同的浏览器中创建XMLHttpRequest 对象使用不同的方法: 先看看IE创建XMLHttpRequest 对象的方法(方法1): var xmlhttp=ActiveXobject("Msxml12.XMLHTTP");//较新的IE版本创建Msxml12.XMLHT

  • 各类Http请求状态(status)及其含义详细解析

    Web服务器响应浏览器或其他客户程序的请求时,其应答一般由以下几个部分组成:一个状态行,几个应答 头,一个空行,内容文档.下面是一个最简单的应答   : 状态行包含HTTP版本.状态代码.与状态代码对应的简短说明信息.在大多数情况下,除了Content-Type之 外的所有应答头都是可选的.但Content-Type是必需的,它描述的是后面文档的MIME类型.虽然大多数应答 都包含一个文档,但也有一些不包含,例如对HEAD请求的应答永远不会附带文档.有许多状态代码实际上用 来标识一次失败的请求,

  • Android天气预报之基于HttpGet对象解析天气数据的方法

    本文实例所述为Android天气预报之解析天气数据的代码,可实现获取HttpGet对象读取天气网站天气数据,并从数据中解析出天气数据,比如温度.温度.风力.风向.未来几天天气趋势.当天天气状况.空气污染指数等信息,还包括了调用对应的图片或天气动画文件,对于开发android天气预报程序的可以参考本文实例. 具体功能代码如下: import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayL

  • C#如何解析http报文

    下面通过一段内容有文字说明有代码分析,并附有展示图供大家学习. 要解析HTTP报文,需要实现以下操作: 读取HTTP报头提供的各种属性 分析属性值,从中获取内容编码和字符集编码 将报头数据和内容进行分离 判断内容是否文本还是二进制,如果是二进制的则不进行处理 如果内容是文本,按报头中提供的内容编码和字符集编码进行解压缩和解码 目前没有找到.Net框架内置的解析方法,理论上HttpClient等类在内部应该已经实现了解析,但不知为何没有公开这些处理方法.(亦或是我没找到) 那么只能自己来解析这些数

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

    关于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,缓存响应数据来减少重复的网络请求

  • Android App开发中HTTP扩展包OkHttp的入门使用指南

    Android 开发,不可避免的会用到网络技术,而多数情况下,我们都是使用 HTTP 协议来发送和接收网络数据.Android 系统主要提供两种方式来进行 HTTP 通信,HttpURLConnection 和 HttpClient,但是从 Android 2.3 及以后版本中,Google 推荐使用 HttpURLConnection,究其原因,就是由于 HttpClient 的 API 数量过多,使得我们很难在不破坏兼容性的情况下对它进行升级和扩展,所以目前 Android 团队在提升和优化

  • 使用Android的OkHttp包实现基于HTTP协议的文件上传下载

    OkHttp的HTTP连接基础 虽然在使用 OkHttp 发送 HTTP 请求时只需要提供 URL 即可,OkHttp 在实现中需要综合考虑 3 种不同的要素来确定与 HTTP 服务器之间实际建立的 HTTP 连接.这样做的目的是为了达到最佳的性能. 首先第一个考虑的要素是 URL 本身.URL 给出了要访问的资源的路径.比如 URL http://www.baidu.com 所对应的是百度首页的 HTTP 文档.在 URL 中比较重要的部分是访问时使用的模式,即 HTTP 还是 HTTPS.这

  • Android Studio 3.0 新功能全面解析和旧项目适配问题

    简介: Android Studio是Android的官方IDE.它是专为Android而打造,可以加快您的开发速度,帮助您为每款Android设备构建最优应用. 它提供专为Android开发者量身定制的工具,其中包括丰富的代码编辑.调试.测试和性能分析工具. 上周四,Google 终于在经历大半年的打磨锤炼之后正式发布 Android Studio 3.0 版本,给广大安卓开发人员一份满意的答卷.如往常一样,每次新版开发工具的发布,很多谨慎点的朋友仍担心稳定性.是否存在坑等问题,选择隔岸观火,

  • Android7.0自动更新适配 包解析异常

    在Android7.0的手机上,自动更新的时候出现包解析异常,在其他的手机上没有这个问题. 原因: Android7.0引入私有目录被限制访问和StrictMode API .私有目录被限制访问是指在Android7.0中为了提高应用的安全性,在7.0上应用私有目录将被限制访问.StrictMode API是指禁止向你的应用外公开 file:// URI. 如果一项包含文件 file:// URI类型 的 Intent 离开你的应用,则会报出异常. 解决办法: 第一步:在AndroidManif

  • java、android可用的rtp封包解包h264案例

    做直播,音视频通讯.经常需要通过rtp协议封装音视频数据来发送.网上找到的基本都是c或c++版本的,没有JAVA版本的.就算千辛万苦找到一篇java版本的,要么不能用,要么就是一些片段,要么有封包没解包. 很是蛋疼,本人也是这样,刚开始不太熟悉rtp协议,不太明白怎么封包组包,痛苦了几天,终于搞出来了,分享给有需要的朋友,希望对你们有所帮助. 直接看代码吧.不多说了. 首先看看关键类: package com.imsdk.socket.udp.codec; import android.os.S

  • Android MeasureSpec的理解和源码的解析

    Android  MeasureSpec的理解和源码的解析 MeasureSpec的创建规则: 实例详解: package cc.ww; import android.view.View; import android.view.View.MeasureSpec; import android.view.ViewGroup.LayoutParams; import android.view.ViewGroup.MarginLayoutParams; import android.widget.L

  • Android程序开发之使用Design包实现QQ动画侧滑效果和滑动菜单导航

    Google在2015的IO大会上,给我们带来了更加详细的Material Design设计规范,同时,也给我们带来了全新的Android Design Support Library,在这个support库里面,Google给我们提供了更加规范的MD设计风格的控件.最重要的是,Android Design Support Library的兼容性更广,直接可以向下兼容到Android 2.2.这不得不说是一个良心之作. 使用方法很简单,只需要添加一句依赖 compile 'com.android

  • Android SDK中的Support兼容包详解

    背景 来自于知乎上邀请回答的一个问题Android中AppCompat和Holo的一个问题?, 看来很多人还是对这些兼容包搞不清楚,那么干脆写篇博客吧. Support Library 我们都知道Android一些SDK比较分裂,为此google官方提供了Android Support Library package 系列的包来保证高版本sdk开发的向下兼容性, 所以你可能经常看到v4,v7,v13这些数字,首先我们就来理清楚这些数字的含义,以及它们之间的区别. support-v4 用在API

  • Android studio利用gradle打jar包并混淆的方法详解

    本文主要介绍了Android studio利用gradle打jar包并混淆的方法,下面话不多说,来看看详细的介绍吧. 首先打jar包的配置很简单,使用jar的task,可以参考gradle官方文档,具体代码如下: task buildJar(type: Jar, dependsOn: ['assembleRelease']) { destinationDir = file('build/outputs/jar/') appendix = "" baseName = "&quo

随机推荐