美文网首页Android随笔
多继承后如何得到父类嵌套泛型的真实类型并使用Gson解析数据

多继承后如何得到父类嵌套泛型的真实类型并使用Gson解析数据

作者: 爱玩单机的人 | 来源:发表于2019-05-14 22:14 被阅读0次

    在做公司项目的时候,有需要缓存和读取缓存数据的需求,网络请求使用retrofit 2.0 + rxjava2 + okhttp3,因此用ResponseObserver继承Observer封装一些接口数据处理逻辑,其中就包括缓存的存储和读取操作,存储此处不做探讨,此处重点探讨的就是缓存读取问题。

    主要类结构:

    public class Response<T> {
        private T data;
        //其它细节省略,接口返回的数据结构主要就是data不一致
    }
    
    abstract class ResponseObserver<T>  extends Observer<Response<T>> {
    
    }
    

    读取有什么问题呢?就是泛型,在存储的时候,存储的数据结构是Response<T>,因此读取时也需要转化成Response<T>。问题就出在这里,java运行时,在ResponseObserver类中无法直接读取Response<T>(强调一下需要读取的是Response<T>这个整体)的Type,Response<T>中泛型T真实类型无法获取,在ResponseObserver中仅读取泛型T的真实类型是可以获取到的。既然获取不到Response<T>的Type,那么我们就无法使用Gson将json格式的缓存数据转化成我们需要的格式。

    // 虽然可能也会得到Response,但是data数据并不是我们指定的类型,大概率是LinkedTreeMap(Gson库提供的对象)
    new Gson().fromJson(json, type)
    

    下面将给出解决方案:

    abstract class ResponseObserver<T>  extends Observer<Response<T>> {
    
       /**
         * 获取缓存数据
         */
        public Response<T> getCacheData(){
            // 下面这样获取Response<T>的Type是没有用的,T的类型将丢失,最终无法将data数据转化成T类型
            // Type type = new TypeToken<Response<T>>() {}.getType();
    
            // 此处借助Gson库中$Gson$Types类提供的方法newParameterizedTypeWithOwner创建自定义的Type
            // 下面自定义Response<T>泛型的Type
            // 在当前类中是可以获取泛型T的真实类型的
            Type[] tActualTypeArguments = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments();
            // 然后获取Response类的Type
            Type rawType = Response.class.getGenericSuperclass();
    
            // 最后生成组合Type,Response<T>的Type
            // $Gson$Types.newParameterizedTypeWithOwner接收三个参数
            // ownerType:所处类的Type,如果不是内部类或嵌套类则均为null。比如Response不是任何类的子类,因此此处为null
            // rawType:真实类型,在此处就是Response的类型
            // typeArguments:类型参数,此处就是Response<T>中泛型T的真实类型的Type,比如已知是Response<String>,
            // 那么typeArguments就是String.class或String.class.getGenericSuperclass(),其实是一样的
            ParameterizedType cusTomeType = $Gson$Types.newParameterizedTypeWithOwner(null, rawType, tActualTypeArguments);
    
            // 然后将Type传给Gson就能转化成我们需要的Response<T>
            String cacheJson = "缓存获取到的Json数据";
            Response<T> response = new Gson().fromJson(cacheJson, cusTomeType);
            return response;
        }
    
        //...
    
        /**
         * 处理数据
         */
        public abstract void dispose(Response<T> response);
    
       //...
    }
    
    // 外部使用
    public void getUserInfo() {
       //...省略一些不必要的细节
       // 此处泛型真实类型为UserInfo,上面的代码最终会将缓存数据转化为Response<UserInfo>
       new ResponseObserver<UserInfo>() {
             @Override
              public void dispose(Response<UserInfo> response) {
                  // 处理业务逻辑
             }
        };
       //...省略一些不必要的细节
    }
    

    相关文章

      网友评论

        本文标题:多继承后如何得到父类嵌套泛型的真实类型并使用Gson解析数据

        本文链接:https://www.haomeiwen.com/subject/oixyaqtx.html