Получить загрузчик классов generics для разбора вложенного поля Parcelable generic

У меня есть оболочка Parcelable generic type, но конструкция Parcel не скомпилируется, потому что класс T не может быть определен в общем случае

 class MyItem<T : Parcelable> (val model: T) : Parcelable { constructor(parcel: Parcel) : this(parcel.readParcelable(T::class.java.classLoader)) { } } 

Есть ли какое-либо решение в этом случае?

Вы можете использовать встроенную функцию reified в качестве заводского метода для достижения этой цели. Я предпочитаю делать это на сопутствующем объекте. Вот MCVE:

 class MyItem<T> (val model: T) { companion object { inline fun <reified T> from(parcel : T) : MyItem<T> { return MyItem<T>(T::class.java.newInstance()) } } } fun main(args: Array<String>) { val mi = MyItem.from("hi") println("mi is a ${mi::class}") } 

Если вам нужен конструктор типа Parcel, вы можете изменить его как основной конструктор и затем определить тип MyItem.

 class Parcel class MyItem(val parcel: Parcel) { inline fun <reified T> model() : T { // You code would be calling // `parcel.readParcelable(T::class.java.classLoader)` return T::class.java.newInstance() as T } } fun main(args: Array<String>) { // You don't ned to know the out type when constructing MyItem. val mi = MyItem(Parcel()) // But you do need to know it when calling model() val model : String = mi.model() println("mi.model is a ${model::class}") } 

Для того, чтобы получить всю картину, вот что я закончил:

Вариант использования: у одного есть экземпляр Parcelable generic, назовем его model которая должна быть дополнена общими свойствами обертки Parcelable , чтобы не загрязнять модель с внешними полями. Например, обертка Item .

В приведенном ниже примере дополнительное свойство wrapper дает нам некоторый тип index :

 class Item<T : Parcelable> (val model: T, val index: Int ) : Parcelable { constructor(parcel: Parcel) : this(parcel.readParcelable( Item<T>::model.javaClass.classLoader), parcel.readInt() ) {} override fun writeToParcel(parcel: Parcel?, flag: Int) { parcel?.writeParcelable(model, 0) parcel?.writeInt(index) } override fun describeContents(): Int { return 0 } companion object CREATOR : Parcelable.Creator<Item<Parcelable>> { override fun createFromParcel(parcel: Parcel): Item<Parcelable> { return Item(parcel) } override fun newArray(size: Int): Array<Item<Parcelable>?> { return arrayOfNulls(size) } } } 

Таким образом, в конце мы можем иметь что-то вроде: Item(Person("John"), 0) , Item(Person("Bill"), 1)

 class PersonPagerFragment() : BasePagerFragment<Person>() { companion object { fun newInstance(itemList: ArrayList<Item<Person>>) : PersonPagerFragment { val args = Bundle() val fragment = PersonPagerFragment() args.putParcelableArrayList("items", itemList) fragment.arguments = args return fragment } } } 

расширяющий класс как:

 class BasePagerFragment<T : Parcelable> : Fragment(){ protected fun readBundle(bundle: Bundle?) { bundle.getParcelableArrayList<Item<T>>("items") } }