在做公司项目的时候,有需要缓存和读取缓存数据的需求,网络请求使用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) {
// 处理业务逻辑
}
};
//...省略一些不必要的细节
}
网友评论