Android探索之基于okHttp打造自己的网络请求(三)

前言:

前面两篇文章介绍了基于okHttp的post、get请求,以及文件的上传下载,今天主要介绍一下如何和Json解析一起使用?如何才能提高开发效率?

关于Json解析:

本文的Json解析采用阿里巴巴的FastJson 解析,也可以采用Gson解析,两者之间的对比请参考文章Android之json解析(FastJson Gson 对比)(http://www.cnblogs.com/whoislcj/p/5468420.html)。

关于泛型:

本文将采用json统一泛型解析,阅读本文之前请先对java泛型知识有一定的了解。

关于反射机制:

本文会采用Java的反射机制来解析泛型对象Class<?>,阅读本文之前请先对Java发射机制知识有一定的了解。

代码实现:

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

小结:如此一来发送请求到解析数据变得So easy !用流行的一句广告语来说的话,那就是老板再也不用担心我搞不定网络请求和json解析了。

时间: 2024-08-23 05:48:30

Android探索之基于okHttp打造自己的网络请求(三)的相关文章

Android探索之基于okHttp打造自己的网络请求(一)

前言: 之前项目中一直使用的Xutils开源框架,从xutils 2.1.5版本使用到最近的xutils 3.0,使用起来也是蛮方便的,只不过最近想着完善一下app中使用的开源框架,由于Xutils里面包含的东西相对来说比较杂,有数据库.图片缓存.注解.网络请求等等,秉着一个开源库只处理一件事的想法,决定逐步替换到Xutils,上网搜了一下比较好的开源框架,就找到了okHttp.volley.android-async-http等比较推荐的开源网络请求,该如何选择呢? okHttp.volley

Android探索之基于okHttp打造自己的网络请求&lt;Cache-Control&gt;(四)

前言: 前面的学习基本上已经可以完成开发需求了,但是在项目中有时会遇到对请求做个缓存,当没网络的时候优先加载本地缓存,基于这个需求我们来学习一直okHttp的Cache-Control. Cache-Control: Cache-Control指定请求和响应遵循的缓存机制.在请求消息或响应消息中设置Cache-Control并不会修改另一个消息处理过程中的缓存处理过程.请求时的缓存指令有下几种: Public指示响应可被任何缓存区缓存. Private指示对于单个用户的整个或部分响应消息,不能被

Android探索之基于okHttp打造自己的网络请求&lt;Retrofit+Okhttp&gt;(五)

前言: 通过上面的学习,我们不难发现单纯使用okHttp来作为网络库还是多多少收有那么一点点不太方便,而且还需自己来管理接口,对于接口的使用的是哪种请求方式也不能一目了然,出于这个目的接下来学习一下Retrofit+Okhttp的搭配使用. Retrofit介绍: Retrofit和okHttp师出同门,也是Square的开源库,它是一个类型安全的网络请求库,Retrofit简化了网络请求流程,基于OkHtttp做了封装,解耦的更彻底:比方说通过注解来配置请求参数,通过工厂来生成CallAdap

React Native探索(五)使用fetch进行网络请求

前言 React Native可以使用多种方式来进行网络请求,比如fetch.XMLHttpRequest以及基于它们封装的框架,fetch可以说是替代XMLHttpRequest的产物,这一节我们就来学习fetch的基本用法. 1.get请求 fetch API是基于 Promise 设计的,因此了解Promise也是有必要的,推荐阅读MDN Promise教程 . get请求访问淘宝IP库 我们先从最基础的get请求开始,get请求的地址为淘宝IP地址库,里面有访问接口的说明.请求代码如下所

基于AFNetWorking搭建APP的网络请求框架[iOS]

自从AFNetWorking(下文简称AFN)更新2.0版本之后,AFN的许多的问题得到的有效的解决,写法也得到了完善.前期主流的第三方网络类库 ASI作者宣布不再维护,国内大多数的主流APP都逐步接受并开始采用AFN.出于各自公司项目的不同需要,大家都会在AFN的基础上加一层不尽相同的封 装.很多新APP在选择方式时也会非常纠结.如何封装才可以让AFN更有效率更方便的应用于项目呢,对于这个问题,各人有各人的看法.基于做过以及读过的 几个项目,也来谈一下如何搭建一个APP的网络请求框架.由于本人

开源的Android开发框架-------PowerFramework使用心得(五)网络请求HTTPRequest

GET请求示例 //所有参数都使用Bundle,用putString Bundle bundle = new Bundle(); bundle.putString("username", "RederXuGet"); bundle.putString("password", "farmerGet"); //url String url = "http://www.baidu.com"; //发起请求 HTT

Android 网络请求详解

我们知道大多数的 Android 应用程序都是通过和服务器进行交互来获取数据的.如果使用 HTTP 协议来发送和接收网络数据,就免不了使用 HttpURLConnection 和 HttpClient,而 Android 中主要提供了上述两种方式来进行 HTTP 操作.并且这两种方式都支持 HTTPS 协议.以流的形式进行上传和下载.配置超时时间.IPv6.以及连接池等功能. 但是 Googl e发布 6.0 版本的时候声明原生剔除 HttpClient,但是笔者认为 HttpClient 会提

OKHttp源码解析之网络请求

OKHttp是square公司的开源项目,当前android开发中最常用的轻量级框架.本文中主要是解析OKHttp是如何建立网络连接,即HttpEngine,Connection中的部分代码.(注:解析的版本是2.5.0版本) 在开始前我们先要确定以下几个问题,这将助于对源码的理解(如果已经清楚的大神可以跳过),问题如下: 1.http同tcp有什么关系? http是应用层协议,依赖于传输层的tcp协议.通俗的讲http就是一个tcp连接,只不过它是以一种"短连接"的形式存在. 2.h

android开发-网络请求Ⅰ

本章讲述在android开发中,常用的网络请求操作.网络请求利用android基本的HttpURLConnection连接URL和开源网络请求包AsyncHttpClient.本次网络请求以调取天气接口查询天气为案例,对请求到的天气数据采用SQLite数据库存储,并利用ContentProvider数据共享模式操作存储数据.本章主要介绍知识点HttpURLConnection,AsyncHttpClient,ContentProvider,Json解析插件GsonFormat及Json解析类Gs