如何在适配器类中对泛型使用数据绑定?

问题描述

我正在尝试在我的适配器类中使用泛型。这是我尝试过的:

class ItemAdapter<I>(
    options: FirestoreRecyclerOptions<I>
): FirestoreRecyclerAdapter<I,ItemAdapter<I>.ItemViewHolder<I>>(options) {
    override fun onCreateViewHolder(parent: ViewGroup,viewType: Int): ItemViewHolder<I> {
        val layoutInflater = LayoutInflater.from(parent.context)
        val dataBinding = inflate(layoutInflater,parent,false)
        return ItemViewHolder(dataBinding)
    }

    override fun onBindViewHolder(holder: ItemViewHolder<I>,position: Int,item: I) {
        holder.bindItem(item)
    }

    inner class ItemViewHolder<I>(
        private val dataBinding: ItemDataBinding
    ) : RecyclerView.ViewHolder(dataBinding.root) {
        fun bindItem(item: I) {
            dataBinding.item = item //Here is the problem
        }
    }
}

这是我的布局文件:

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data class="ItemDataBinding">
        <variable
            name="item"
            type="com.example.myapp.Item" />
    </data>

    <TextView
        android:id="@+id/item_name_text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@{item.name}" />
</layout>

我已经添加了item对象,因此可以访问name字段。但是,Android Studio在这一行抱怨:

dataBinding.item = item

使用:

Type mismatch.
Required: Item!
Found: I

如何正确使用泛型并摆脱此问题?谢谢

编辑:

我不需要使特定的类通用。我需要以某种方式将item对象转换为特定类的对象。我试图在名为classType: Class<I>的类中添加一个新属性,并使用以下方法对其进行强制转换:

dataBinding.item = item as classType

但是没有任何运气。我也尝试过:

dataBinding.item = item as I

再次没有运气。

解决方法

该错误表明,您需要将项目强制转换为键入Item而不是I。这是有道理的,因为您的布局以类型Item声明了变量。但是,ViewHolder提供了不受约束类型I的对象,该对象显然不符合Item

您可以将泛型类型I约束为Item的子类型,而不是强制类型转换:

class ItemAdapter<I: Item>(...) {
...
    inner class ItemViewHolder<I: Item>(...) {...}
}

这应该使分配dataBinding.item = item有效。

有些不相关:我认为没有必要为内部类重新声明泛型I。您应该只能使用外部类I的{​​{1}}。

我不得不承认我不完全了解您的代码,因此我可能会遗漏一些东西。供您参考,这是我在项目中使用的具有数据绑定的适配器的非常相似的实现。它允许可配置的布局。它唯一假设的是一个名为ItemAdapter<I: Item>的绑定变量。

model
,

具有dataBinding的通用适配器类:

class BaseAdapter<S>(
    private val mContext: Context?,private var list: List<S>?,//generic list can take any Object 
    private val layoutId: Int,// the item_layout 
    private val listener: BaseAdapterListener? =null// call back inside your view
) : RecyclerView.Adapter<BaseAdapter.DataBindingViewHolder>() {


    override fun onCreateViewHolder(parent: ViewGroup,viewType: Int): DataBindingViewHolder {
        val layoutInflater = LayoutInflater.from(mContext)
        return DataBindingViewHolder(DataBindingUtil.inflate(layoutInflater,layoutId,parent,false))
    }

    override fun getItemCount(): Int {
        return list?.size ?: 0
    }

    fun getItem(position: Int):S {
        list?.let {
            if (position < it.size)
                return it[position]
        }
            return list?.get(position) ?: null as S
    }

    override fun onBindViewHolder(holder: DataBindingViewHolder,position: Int) {
        listener?.onBind(holder,position)
    }

    interface BaseAdapterListener {
        fun onBind(holder: DataBindingViewHolder,position: Int)
    }

    class DataBindingViewHolder( val binding: ViewDataBinding) : RecyclerView.ViewHolder(binding.root)
}

这是您可以在Fragment中使用它的方式:

class DemoFragment : Fragment(),BaseAdapter.BaseAdapterListener {
    private var  adapter: BaseAdapter<Audio>?= null// specify your data it taking List<Audio> as parameter
    
    private  lateinit var binding: FragmentPracticeBinding
    override fun onCreateView(
        inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?
    ): View? {
         super.onCreateView(inflater,container,savedInstanceState)
        binding = FragmentPracticeBinding.inflate(inflater,false)
        return binding.root;
    }

    override fun onViewCreated(view: View,savedInstanceState: Bundle?) {
        adapter = BaseAdapter(context,arrayListOf(),R.layout.item_audio,this)//created the object of adapter with specific info 
        binding.notesRecyclerView.adapter = adapter
    }

    override fun onBind(holder: BaseAdapter.DataBindingViewHolder,position: Int) {
        (holder.binding as ItemAudioBinding).apply { 
            // play with your item layout 
        }
        // this nothing but your onBindViewHolder of item_layout type
    }
}

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...