Я не могу получить список универсального типа из пользовательского класса (Turns):
val turnsType = TypeToken<List<Turns>>() {}.type val turns = Gson().fromJson(pref.turns, turnsType)
он сказал:
cannot access '<init>' it is 'public /*package*/' in 'TypeToken'
Создайте это встроенное удовольствие:
inline fun <reified T> Gson.fromJson(json: String) = this.fromJson<T>(json, object: TypeToken<T>() {}.type)
и тогда вы можете назвать это следующим образом:
val turns = Gson().fromJson<Turns>(pref.turns) // or val turns: Turns = Gson().fromJson(pref.turns)
ПРИМЕЧАНИЕ . Этот подход не был возможен ранее в старых версиях плагинов kotlin, но теперь вы можете его использовать.
Предыдущие альтернативы:
АЛЬТЕРНАТИВА 1:
val turnsType = object : TypeToken<List<Turns>>() {}.type val turns = Gson().fromJson<List<Turns>>(pref.turns, turnsType)
Вы должны поместить object :
и конкретный тип fromJson<List<Turns>>
АЛЬТЕРНАТИВА 2:
Как @cypressious упомянуть, что может быть достигнуто также следующим образом:
inline fun <reified T> genericType() = object: TypeToken<T>() {}.type
использовать как:
val turnsType = genericType<List<Turns>>()
Это решает проблему:
val turnsType = object : TypeToken<List<Turns>>() {}.type val turns = Gson().fromJson<List<Turns>>(pref.turns, turnsType)
Первая строка создает выражение объекта, которое происходит от TypeToken
а затем получает от него Type
Java. Тогда метод Gson().fromJson
либо нуждается в типе, указанном для результата функции (который должен соответствовать созданному TypeToken
). Две версии этой работы, как указано выше, или:
val turns: List<Turns> = Gson().fromJson(pref.turns, turnsType)
Чтобы упростить создание TypeToken
вы можете создать вспомогательную функцию, которая должна быть встроенной, чтобы она могла использовать параметры типа reified :
inline fun <reified T> genericType() = object: TypeToken<T>() {}.type
Которые затем могут быть использованы одним из следующих способов:
val turnsType = genericType<List<Turns>>() // or val turnsType: List<Turns> = genericType()
И весь процесс может быть завернут в функцию расширения для экземпляра Gson
:
inline fun <reified T> Gson.fromJson(json: String) = this.fromJson<T>(json, object: TypeToken<T>() {}.type)
Чтобы вы могли просто позвонить Gson и не беспокоиться о TypeToken
:
val turns = Gson().fromJson<Turns>(pref.turns) // or val turns: Turns = Gson().fromJson(pref.turns)
Здесь Kotlin использует вывод типа с одной стороны задания или другой, и повторно генерирует обобщения для встроенной функции, которая проходит через полный тип (без стирания) и использует это для создания TypeToken
а также делает вызов Gson
Это работает также и проще
inline fun <reified T> Gson.fromJson(json: String) : T = this.fromJson<T>(json, T::class.java)
Другой вариант (не уверенный, что он выглядит более элегантным, чем другие) может вызвать такой вызов:
turns = Gson().fromJson<Array<Turns>>(allPurchasesString, Array<Turns>::class.java).toMutableList()
Таким образом, вы используете линейку класса Java java Array вместо «чистого котлина».