【问题标题】:How to create object of a reified type in Kotlin如何在 Kotlin 中创建具体类型的对象
【发布时间】:2018-05-24 13:42:03
【问题描述】:

我试图创建一个扩展函数来为回收器视图适配器创建视图持有者对象

inline fun <reified T: RecyclerView.ViewHolder> ViewGroup.createViewHolder(@LayoutRes res: Int): T {
    val inflater = LayoutInflater.from(context)
    val itemView = inflater.inflate(res, this, false)
    // return ViewHolder Object
}

如何创建扩展 RecyclerView.ViewHolder 的 T 类型对象,以便我可以从函数返回。

【问题讨论】:

    标签: android kotlin android-recyclerview kotlin-extension kotlin-reified-type-parameters


    【解决方案1】:

    一个干净的替代解决方案是显式传递构造函数。它甚至不会更冗长,因为可以推断类型参数并且不再需要指定。像这样使用:

    val viewHolder = my_view_group.create(::MyViewHolder, R.layout.my_layout)
    

    这样实现:

    inline fun <reified T: RecyclerView.ViewHolder> ViewGroup.create(createHolder: (View) -> T, @LayoutRes res: Int): T {
        val inflater = LayoutInflater.from(context)
        val itemView = inflater.inflate(res, this, false)
        return createHolder(itemView)
    }
    

    【讨论】:

    • 你也可以用::(函数引用)来引用构造函数?我不知道,酷!
    【解决方案2】:

    这个解决方案很丑陋,但我假设“理论上”可以工作:

    inline fun <reified T: RecyclerView.ViewHolder> ViewGroup.create(@LayoutRes res: Int): T {
            val inflater = LayoutInflater.from(context)
            val itemView = inflater.inflate(res, this, false)
            return T::class.java.getConstructor(View::class.java).newInstance(itemView)
        }
    

    最后一行的作用是: 1.获取匹配T(view: View)T的构造函数 2. 在该构造函数上调用newInstance,将你膨胀的视图传递给它

    解决方案改编自https://discuss.kotlinlang.org/t/generic-object-creation/1663/5

    只需通过以下方式调用它:

    val viewHolder = my_view_group.create<MyViewHolder>(R.layout.my_layout)
    

    【讨论】:

    • 我知道这是可能的解决方案,但想知道这是创建 ViewHolder 的好方法吗?反思是好事吗?
    • 嗯,反射从来都不是很好。在这里,可能会发生很多事情,例如更新 ViewHolder 的创建方式(例如,不使用 View 作为参数)。我不相信你会从调用它而不是简单的 MyViewHolder(LayoutInflater.from(parent.context).inflate(R.layout .my_layout, parent, false)) 中获得很多收益
    【解决方案3】:

    不是上述问题的答案,但应该对那些想要摆脱Thing(Foo::class.java, ...)并使用Thing&lt;Foo&gt;(...)的人有所帮助。

    您需要做的就是在companion object 中添加一个具体化的invoke

    之前

    class Thing<E : Enum<E>>(cls: Class<E>, value: String? = null) : Iterable<E> {
        ...
    }
    
    val thing = Thing(Foo::class.java, ...)
    

    之后

    class Thing<E : Enum<E>>(cls: Class<E>, value: String? = null) : Iterable<E> {
        ...
        companion object {
            // Lets us construct using Thing<Foo>(...) instead of Thing(Foo::class.java, ...)
            inline operator fun <reified T : Enum<T>> invoke(value: String? = null) = Thing(T::class.java, value)
        }
    }
    
    val thing = Thing<Foo>(...)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-27
      • 1970-01-01
      • 2019-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-09
      • 2022-06-11
      相关资源
      最近更新 更多