将类传递给Kotlin函数以在适配器中创建ViewHolder

时间:2019-04-01 07:44:08

标签: android generics kotlin

我有一个抽象类:

abstract class AbstractViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)

还有几个孩子:

class LabelViewHolder(itemView: View) : AbstractViewHolder(itemView) {
    val name: TextView = itemView.label
}

class ButtonViewHolder(itemView: View) : AbstractViewHolder(itemView) {
    val name: TextView = itemView.button
}

onCreateViewHolder()中,我想绕过when的所有ViewType:

return when (viewType) {
    ViewType.LABEL.id -> {
        val view = LayoutInflater.from(viewGroup.context).inflate(R.layout.row_label, viewGroup, false)
        LabelViewHolder(view)
    }
    ViewType.BUTTON.id -> {
        val view = LayoutInflater.from(viewGroup.context).inflate(R.layout.row_button, viewGroup, false)
        ButtonViewHolder(view)
    }

为了不对许多when分支写相同的内容,我想使用如下函数:

return when (viewType) {
    ViewType.LABEL.id -> getNewViewHolder(viewGroup, R.layout.row_label, LabelViewHolder::class.java)
    ViewType.BUTTON.id -> getNewViewHolder(viewGroup, R.layout.row_button, ButtonViewHolder::class.java)
}

private fun getNewViewHolder(viewGroup: ViewGroup, @LayoutRes layoutRes: Int, cls: Class<out AbstractViewHolder>): AbstractViewHolder {
    val view = LayoutInflater.from(viewGroup.context).inflate(layoutRes, viewGroup, false)
    return cls.newInstance() // cls(view) is not allowed.
}

如您所见,我无法返回AbstractViewHolder子对象,因为它不允许我创建带有参数view的类。是否可以将类传递给函数并创建其对象?

2 个答案:

答案 0 :(得分:1)

使函数具有通用化的参数化参数。像这样:

private inline fun <reified T> create(parent: ViewGroup, @LayoutRes layoutRes: Int): T {
    return T::class.java.constructors[0].newInstance(
            LayoutInflater.from(parent.context).inflate(layoutRes, parent, false)
    ) as T
}

然后

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AbstractViewHolder {
    return when (viewType) {
        0 -> create<LabelViewHolder>(parent, R.layout.abc_search_view)
        else -> create<ButtonViewHolder>(parent, R.layout.abc_action_menu_item_layout)
    }
}

现在,您可以访问T java对象并调用propert构造器。 这应该在调试中起作用,要发布,请记住要确保proguard不会删除您使用的构造函数。

答案 1 :(得分:0)

请参见https://stackoverflow.com/a/63690450/2914140

override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): AbstractViewHolder {
    return when (viewType) {
        LABEL -> createItem(viewGroup, R.layout.row_label, ::LabelViewHolder)
        BUTTON -> createItem(viewGroup, R.layout.row_button, ::ButtonViewHolder)
        else -> throw IllegalStateException("Wrong class")
    }
}

private fun <T> createItem(
    viewGroup: ViewGroup,
    layoutRes: Int,
    method: (View) -> T
): T {
    val view = LayoutInflater.from(viewGroup.context).inflate(layoutRes, viewGroup, false)
    return method(view) // Creates T(view).
}