Android随笔

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

2019-05-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) {
              // 处理业务逻辑
         }
    };
   //...省略一些不必要的细节
}
上一篇下一篇

猜你喜欢

热点阅读