You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin通用ViewHolder绑定对象至TextView的赋值问题及解决方案

通用RecyclerView ViewHolder对象绑定TextView的问题与解决方案

问题背景

我实现了一个通用RecyclerView ViewHolder,目标是把任意对象绑定到对应视图上。目前已完成从对象读取数据、从视图绑定类获取字段名的操作,但在为TextView赋值objectValue时遇到阻碍。

最初的思路是遍历绑定类的字段,调用对象的属性读取方法(布局元素与对象字段同名),但尝试通过反射访问binding字段并调用setText时,出现类型转换等异常。

最初的代码实现:

class UniversalViewHolder<T : Any>(val bindingAny: ViewDataBinding) : RecyclerView.ViewHolder(bindingAny.root){
    fun bind(elemAny: Any){
        var binding = bindingAny.javaClass
        binding.fields.forEach {
            try {
                val objectValue = readInstanceProperty<String>(elemAny,it.name)
                Log.d(TAG,it.name+" "+objectValue)
                if (it.type == TextView::class.java){
                    // 此处尝试绑定但失败
                }
            }catch (ex: NoSuchElementException){
                Log.e(TAG, "NO ELEMENT AT THIS FIELD "+ it.name)
            }catch (ex:Exception){
                Log.e(TAG,"CRASH AT THIS ELEM: " + it.name+"\n"+ex.stackTraceToString())
            }
        }
    }
}

遇到的具体问题

  • 通过binding.fields获取Field对象后,无法直接修改TextView的文本内容
  • 调用setText方法时触发类型转换异常

最终解决方案

通过递归遍历视图树,收集所有TextView(包括MaterialTextView),再通过资源名称匹配字段名的方式,将对应数据赋值给目标TextView。

完整实现代码

1. 更新后的绑定方法

fun bind(elemAny: Any,context: Context){
    val binding = bindingAny.javaClass

    binding.fields.forEach { field ->
        try {
            val objectValue = readInstanceProperty<String>(elemAny,field.name)
            Log.d(TAG,field.name+" "+objectValue)
            if (field.type == TextView::class.java){

                arrayTextView.forEach {
                    if(context.resources.getResourceName(it.id).contains(field.name)){
                        it.text = objectValue
                    }
                }
            }
        }catch (ex: NoSuchElementException){
            Log.e(TAG, "NO ELEMENT AT THIS FIELD "+ field.name)
        }catch (ex:Exception){
            Log.e(TAG,"CRASH AT THIS ELEM: " + field.name+"\n"+ex.stackTraceToString())
        }
    }
}

2. 视图树遍历收集TextView方法

private var arrayTextView : ArrayList<TextView> = ArrayList()
private fun searchLeaf(root: ViewGroup,context: Context){
    while(true){
        root.forEach {
            if(it::class == MaterialTextView::class || it::class == TextView::class){
                Log.d(TAG,context.resources.getResourceName(it.id))
                arrayTextView.add(it as TextView)
            }
            else if((it as ViewGroup).size != 0){
                try{
                    searchLeaf(it as ViewGroup,context)
                }catch (ex:Exception){ }
            }
        }
        break
    }
}

内容的提问来源于stack exchange,提问作者Daniel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 00:50:13