问题描述
我有一个使用具体化泛型的内联函数,如下所示。它在伴随对象内,因此是静态的:
inline fun <reified T> getListFromPreferences(preferences : SharedPreferences,key : String)
: MutableList<T> {
return try {
val listAsstring = preferences.getString(key,"")
val type: Type = object : Typetoken<List<T>>() {}.type
val gson = SMSApi.gson
gson.fromJson<ArrayList<T>>(listAsstring,type)
?: ArrayList()
}catch(exception: JsonSyntaxException) {
ArrayList()
}
}
当我使用仪器测试对其进行测试以及在应用程序本身中使用它时,它运行得非常好。但是,我在后台服务调用该函数时,抛出了致命异常,说是非法类型变量引用,退出app:
E/AndroidRuntime: FATAL EXCEPTION: Thread-10
Process: example.app,PID: 20728
java.lang.AssertionError: illegal type variable reference
at libcore.reflect.TypeVariableImpl.resolve(TypeVariableImpl.java:111)
at libcore.reflect.TypeVariableImpl.getGenericDeclaration(TypeVariableImpl.java:125)
at libcore.reflect.TypeVariableImpl.hashCode(TypeVariableImpl.java:47)
at com.google.gson.internal.$Gson$Types$WildcardTypeImpl.hashCode($Gson$Types.java:595)
at java.util.Arrays.hashCode(Arrays.java:4074)
at com.google.gson.internal.$Gson$Types$ParameterizedTypeImpl.hashCode($Gson$Types.java:502)
at com.google.gson.reflect.Typetoken.<init>(Typetoken.java:64)
at example.app.NotificationService$remoteNotificationReceived$$inlined$let$lambda$1$1.<init>(PreferenceHelper.kt:16)
at example.app.NotificationService$remoteNotificationReceived$$inlined$let$lambda$1.run(NotificationService.kt:63)
at java.lang.Thread.run(Thread.java:764)
inline fun <reified T> getListFromPreferences(preferences : SharedPreferences,type)
?: ArrayList()
}catch(exception: JsonSyntaxException) {
ArrayList()
}
}
后台服务是实现Onesignal的OSRemoteNotificationReceivedHandler的NotificationService。该函数在 onNotificationReceived() 方法中抛出异常。 有什么我不明白的原因,为什么在应用程序(前台)中内联很好,但在后台抛出异常?或者有什么办法可以解决这个问题?
class NotificationService : Onesignal.OSRemoteNotificationReceivedHandler {
override fun remoteNotificationReceived(context: Context?,notificationReceivedEvent: OSNotificationReceivedEvent?) {
notificationReceivedEvent?.let {
val data = notificationReceivedEvent.notification.additionalData
if(context != null) {
//Fetch some vals
Thread {
val result = //Insert data in db
//-1 will be returned,for rows that are not inserted.
//Rows will not be inserted,if they hurt a unique constraint.
//Therefore the following code should only be executed,when it is inserted.
if(result[0]!=-1L) {
//Get preferences,create item
val list = PreferenceHelper
.getListFromPreferences<MessageAckNowledgement>
(preferences,App.ACKNowLEDGE_IDS) -> throws error
list.add(ackNowledgeMessage)
PreferenceHelper.setListInPreferences(preferences,App.ACKNowLEDGE_IDS,list)
//Do some more stuff
}
}.start()
}
Log.d("NotificationService",data.toString())
notificationReceivedEvent.complete(notificationReceivedEvent.notification)
}
}
}
解决方法
我不确定上面的代码有什么问题,它需要共享更多的代码,但是 Kotlin 有一种获取 Type
令牌的本机方式。只需替换:
object : TypeToken<List<T>>() {}.type
与:
typeOf<List<T>>().javaType
由于 typeOf()
仍处于试验阶段,您需要使用以下内容注释您的函数:@OptIn(ExperimentalStdlibApi::class)
。我已经使用它一段时间了,从来没有出现过任何问题,所以我想它使用起来非常安全,至少在 JVM 上是这样。