what is the best of creating a generic object that...
# announcements
a
what is the best of creating a generic object that has an argument in its constructor. For instance if I just need to create a new object that the class does not have arguments in its contructor I would be able to make
Copy code
T::class.java.newInstance() // Where T is a generic type
But, if I want to make an new object that need to receive an argument. The usage of this would be in a recycler view where I have different view holders but each one has a constructor with only one argument. like
Copy code
inner class ShortTextViewHolder(
        private val viewBinding: ItemRowFormFieldTextBinding
    ) : RecyclerView.ViewHolder(viewBinding.root), FieldViewHolder {

        override fun configureWith(field: FormField) = viewBinding.run {
            with(field) {
                textFieldName.text = label
                textFieldDescription.text = description
            }
        }
    }
So basically, I would like to simplify this
Copy code
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val view = ItemRowFormFieldTextBinding.inflate(parent.inflater)
        if (viewType == ITEM_TYPE_SHORT_TEXT) {
            return ShortTextViewHolder(view)
        }
        return LongTextViewHolder(view)
    }
By calling a Factory like
factory<LongTextViewHolder>(view)
or
factory(view, myPossibleTypes[viewType])
where
myPossibleTypes
would be a list of the types I can instantiate
a
you need to go through
getConstructor(..)
and call
newInstance(..)
on the Constructor returned rather than simply calling
newInstance
on the class (which is a shortcut for
.getConstructor().newInstance()
)
t
What do you need is the old reflection concept to create instances using they constructor.
Copy code
data class ViewHolder(val name: String)

inline fun <reified T> check() {
    val instance = T::class.constructors.first().apply {
        isAccessible = true
    }.call("Amadeu")
    println(">>>>> My name is: $instance")
}

fun main() {
    check<ViewHolder>()
}
Warning: I don't recomend to use reflection in the Android context, because can create bugs not easy to find.
Don't forget to scape classes in the Proguard, Dexguard, R8 files and
kotlin-reflect
dependency
a
I managed to do something like
Copy code
inline fun <reified Field: FieldHolder, View: ViewBinding> myFactory(view: View, init: (View) -> Field): Field {
    return init(view)
}

myFactory<ShortTextViewHolder, ItemRowFormFieldTextBinding>(view, ::ShortTextViewHolder)
// or
val field = myFactory(view, ::ShortTextViewHolder)
Which is basically calling the constructor. Is this
::MyClass
using reflection ?
a
I don’t think that uses reflection, as its making a reference to the constructor all at compile time, so there’s no need, it’s essentially just a
{view -> ShortTextViewHolder(view) }
lambda