突出类型禁止使用方法

时间:2018-06-26 18:04:59

标签: android generics kotlin

我似乎无法绕过Kotlin仿制药,请帮忙

我阅读了herehere,但仍然不确定如何进行这项工作。我有一个RecyclerView适配器,该适配器使用抽象的父BaseFieldVH作为ViewHolder类。

所以Adapter类看起来像这样:

class MyAdapter() : RecyclerView.Adapter<BaseFieldVH<*>>() {
... 
    override fun onBindViewHolder(holder: BaseFieldVH<*>, position: Int) {
        holder.bind(data[position])
    }
}

ViewHolder实现如下所示:

abstract class BaseFieldVH<in FF : BaseFormField>
    (itemView: View) : RecyclerView.ViewHolder(itemView) {
    ...
    abstract fun bind(formField: FF)
}

但是实际调用holder.bind(data[position])时显示错误:

Out-projected type 'BaseFieldVH<*>' prohibits the use of 'public 
abstract fun bind(formField: FF): Unit defined in ...

什么都不用?

我也尝试使用BaseFieldVH<in Nothing>定义适配器,但是由于尝试将Nothing放到需要BaseFormField的函数中而出现类型不匹配错误。

使用BaseFormField

使用BaseFieldVH<iBaseFormField>定义适配器实际上可以解决绑定问题,但是在onCreateViewHolder中,视图持有者的类型不匹配:

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseFieldVH<BaseFormField> {
    val itemView: View
    when (viewType) {
        HEADER_TYPE -> {
            itemView = LayoutInflater.from(parent.context)
                    .inflate(R.layout.item_header, parent, false)
            return HeaderVH(itemView)
        }

HeaderVH是BaseFieldVH的扩展,因此类型不匹配

2 个答案:

答案 0 :(得分:2)

此问题的答案似乎是您无法实现为绑定指定泛型的ViewHolder类。我的猜测是因为编写了RecyclerView.Adapter Java和任何Kotlin扩展都太严格而无法正确实现。

如果您可以反驳这个结论,请告诉我!

我发现this帖子以我能理解的方式解释了整个投影概念。

最后,我放弃了控制ViewHolder的Type的尝试:

abstract class BaseFieldVH
  (itemView: View) : RecyclerView.ViewHolder(itemView) {
  ...
  abstract fun bind(formField: Any)
}

这意味着BaseFieldVH的每个子类都必须在其绑定函数中进行某种类型检查。例如:

class HeaderVH
  (itemView: View) : BaseFieldVH(itemView) {
...
  override fun bind(headerField: Any) {
    if (headerField is HeaderField) {
      // do something
    }
}

}

但是现在至少我没有收到任何错误。

答案 1 :(得分:0)

如果数据列表中有多个复杂对象(为了在回收者视图中显示不同的项目),则还需要指定您的所有者。

这里的想法是您提供适配器,而不是由Holder来决定如何处理每种对象类型。

class MyAdapter() : RecyclerView.Adapter<BaseFieldVH<*>>() {
    ... 

    override fun onBindViewHolder(holder: BaseFieldVH<*>, position: Int) {
        val item = data[position]

        holder as BaseFieldVH<DATA_ITEM_TYPE>
        item as DATA_ITEM_TYPE

        holder.bind(item)
    }
}