Android 将类传递给Kotlin函数以在适配器中创建ViewHolder
我有一个抽象类:Android 将类传递给Kotlin函数以在适配器中创建ViewHolder,android,generics,kotlin,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:
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分支编写相同的代码,我想使用如下函数:
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的类。是否可以将类传递给函数并创建其对象?使用泛型具体化参数生成函数。像这样:
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 constructor。
这应该可以在调试中使用,对于发布版,请记住确保proguard不会删除您使用的构造函数。请参阅
我在这里遇到了一个问题。在发布版本中,我们无法使用反射并获取异常:java.lang.ArrayIndexOutOfBoundsException:length=0;索引=0。所以,如果我们想使用这段代码,我们应该在proguard-rules.pro中添加所有创建的viewholder:-keepattributes Signature、innerClass、EnclosingMethod和更高版本:-为所有viewholder保留class com.package.presentation.YourAdapter$ButtonViewHolder{*;}等等。我现在可以试试,但也许不要混淆从某个AbstractViewHolder继承的所有类。或者使用注释@dontobfuscate,我相信这是可能的,它可以帮助您。虽然我回来创建了几个类似的类,但应该是我不能,我不认为今天,我也不能编辑最后的评论xD对不起。无论如何,让我知道它是否有效;
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)
}
}
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).
}