Android 解決Gson泛型解析


由於泛型在運行時被抹除,所以無法直接通過對象實例或class獲取,在老版本的Gson里可以通過一下方法獲取實際類型:

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

但是Gson 2.8.6內TypeToken構造方法已經不再公開:

解決方案:

  1. 使用Gson提供的創建TypeToken的公開靜態方法:
  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,不需要額外依賴。

2020-03-03


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM