Android混淆导致无法反射获取泛型类型

302 阅读1分钟

现象:Child继承Parent并声明了泛型类型

class Parent<T>{...}
class TestViewModel extends ViewModel{...}
class Child extends Parent<TestViewModel>{...}
Child c = new Child();

通过反射获取对象c的泛型类型偶尔会返回java.lang.Object类型。

原因:混淆时会将未用到泛型信息擦除,即在对象c未使用到泛型T相关的方法或对象时;

解决:修改混淆规则

#保持泛型
-keepattributes Signature
-keepattributes Exceptions
#对应泛型Tclass不混淆
-keep public class * extends androidx.lifecycle.ViewModel

反射获取泛型类型的方法:

public static <T> Class<T> getGenericClass(Class<?> klass) {
    Type type = klass.getGenericSuperclass();
    if (!(type instanceof ParameterizedType)) return null;
    ParameterizedType parameterizedType = (ParameterizedType) type;
    Type[] types = parameterizedType.getActualTypeArguments();
    if (types.length == 0) return null;
    return (Class<T>) types[0];