Android R8混淆致Gson无法实例化NetworkPagingList问题排查
问题分析与解决:Gson无法实例化泛型数据类(R8混淆导致)
报错信息
java.lang.RuntimeException: Unable to invoke no-args constructor for class com.arch.example.network.models.NetworkPagingList. Registering an InstanceCreator with Gson for this type may fix this problem. at com.google.gson.internal.ConstructorConstructor$14.construct(ConstructorConstructor.java:228) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:212) at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:40) at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:27) at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:243) at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:153) at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:519) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637) at java.lang.Thread.run(Thread.java:1012) Caused by: java.lang.UnsupportedOperationException: Abstract class can't be instantiated! Class name: com.arch.example.network.models.NetworkPagingList at com.google.gson.internal.UnsafeAllocator.assertInstantiable(UnsafeAllocator.java:120) at com.google.gson.internal.UnsafeAllocator$1.newInstance(UnsafeAllocator.java:49) at com.google.gson.internal.ConstructorConstructor$14.construct(ConstructorConstructor.java:225) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:212) at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:40) at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:27) at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:243) at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:153) at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:519) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637) at java.lang.Thread.run(Thread.java:1012)
实体类代码
import com.google.gson.annotations.SerializedName data class NetworkPagingList<T>( @SerializedName("data") val data: List<T> )
使用场景
@GET("worker/shifts") suspend fun getShifts( @Query("page") page: Int, @Query("perPage") perPage: Int ): NetworkPagingList<NetworkShift>
问题原因
升级Android Gradle插件(AGP)后,R8混淆器的默认优化规则变得更激进,导致泛型数据类NetworkPagingList<T>被误处理:
- R8可能移除了该类的反射元数据,甚至错误地将其标记为抽象类(从报错的
Abstract class can't be instantiated可直接看出) - Kotlin data类默认只有带参构造函数,Gson原本可以通过反射调用,但R8的优化破坏了这一逻辑,使得Gson找不到合法的构造方式,进而抛出无法实例化的异常
解决方法
方案1:添加R8混淆保护规则
在项目的proguard-rules.pro文件中添加以下规则,保留NetworkPagingList类的构造函数和反射元数据:
# 保留泛型数据类的构造函数与字段 -keep class com.arch.example.network.models.NetworkPagingList { <init>(...); <fields>; } # 保留Gson反射所需的签名信息 -keepattributes Signature, InnerClasses
方案2:给数据类添加无参构造函数
修改Kotlin data类,给字段设置默认值,让编译器自动生成无参构造函数,Gson可以直接调用:
data class NetworkPagingList<T>( @SerializedName("data") val data: List<T> = emptyList() )
方案3:注册Gson InstanceCreator
按照报错提示,手动给NetworkPagingList注册实例创建器,让Gson知道如何生成该类的实例:
// 创建自定义Gson实例 val customGson = GsonBuilder() .registerTypeAdapter(NetworkPagingList::class.java, InstanceCreator<NetworkPagingList<*>> { NetworkPagingList(emptyList()) }) .create() // 传给Retrofit val retrofit = Retrofit.Builder() .baseUrl("你的基础URL") .addConverterFactory(GsonConverterFactory.create(customGson)) .build()
内容的提问来源于stack exchange,提问作者user924
相关产品推荐
相关产品推荐

