Android 解决Gson泛型解析

91 阅读1分钟

由于泛型在运行时被抹除,所以无法直接通过对象实例或class获取,在老版本的Gson里可以通过一下方法获取实际类型:

Type type = new TypeToken<Test>(){}.getType();

但是Gson 2.8.6内TypeToken构造方法已经不再公开: 11880671-e4699e175f25c4c8.png

解决方案:

  1. 使用Gson提供的创建TypeToken的公开静态方法: 11880671-88172bafe17cb349.png
  2. 通过自定义Type类,将泛型内容写进去
public class ParameterizedTypeImpl implements ParameterizedType {
    @Nullable
    private final Type ownerType;
    private final Type rawType;
    private final Type[] typeArguments;

    public ParameterizedTypeImpl(@Nullable Type ownerType, Type rawType, Type... typeArguments) {
        // Require an owner type if the raw type needs it.
        if (rawType instanceof Class<?>
                && (ownerType == null) != (((Class<?>) rawType).getEnclosingClass() == null)) {
            throw new IllegalArgumentException();
        }

        for (Type typeArgument : typeArguments) {
            Objects.requireNonNull(typeArgument, "typeArgument == null");
            TypeUtil.checkNotPrimitive(typeArgument);
        }

        this.ownerType = ownerType;
        this.rawType = rawType;
        this.typeArguments = typeArguments.clone();
    }

    @NonNull
    @Override
    public Type[] getActualTypeArguments() {
        return typeArguments.clone();
    }

    @NonNull
    @Override
    public Type getRawType() {
        return rawType;
    }

    @Override
    public @Nullable
    Type getOwnerType() {
        return ownerType;
    }

    @Override
    public boolean equals(Object other) {
        return other instanceof ParameterizedType && TypeUtil.equals(this, (ParameterizedType) other);
    }

    @Override
    public int hashCode() {
        return Arrays.hashCode(typeArguments)
                ^ rawType.hashCode()
                ^ (ownerType != null ? ownerType.hashCode() : 0);
    }

    @NonNull
    @Override
    public String toString() {
        if (typeArguments.length == 0) return TypeUtil.typeToString(rawType);
        StringBuilder result = new StringBuilder(30 * (typeArguments.length + 1));
        result.append(TypeUtil.typeToString(rawType));
        result.append("<").append(TypeUtil.typeToString(typeArguments[0]));
        for (int i = 1; i < typeArguments.length; i++) {
            result.append(", ").append(TypeUtil.typeToString(typeArguments[i]));
        }
        return result.append(">").toString();
    }
}

上述2种方法本质上都是创建自定义Type,将泛型信息保存在内,差别在与方案2代码来自retrofit2,不需要额外依赖。