如何解决如何在适配器类中对泛型使用数据绑定?
我正在尝试在我的适配器类中使用泛型。这是我尝试过的:
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
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。