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

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

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

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 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-