【问题标题】:Manually created view in ViewHolder created in onCreateViewHolder在 onCreateViewHolder 中创建的 ViewHolder 中手动创建的视图
【发布时间】:2018-03-29 17:29:59
【问题描述】:

我想制作一个通用适配器,让我重用它。这就是为什么我决定不通过inflating 创建视图,而是将自定义的、先前创建的视图传递给ListAdapter 中的ViewHolderonCreateViewHolder 中的RecyclerView)。根据其文档,这应该是可能的,因为它说:

您可以手动创建新视图,也可以从 XML 布局文件扩充它。

这是我的适配器实现:

class BaseAdapter<T, V : View>(
        private val adapterConfig: AdapterConfig<T, V>,
        private val onClick: (T) -> (Unit)
) : ListAdapter<T, BaseViewHolder<V>>(adapterConfig.diffCallback) {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder<V> {
        return adapterConfig.viewHolder.apply {
            itemView.setOnClickListener { onClick(getItem(adapterPosition)) }
        }
    }

    override fun onBindViewHolder(holder: BaseViewHolder<V>, position: Int) {
        adapterConfig.bind(getItem(position), holder, position)
    }
}

AdapterConfig 实现类可用于创建ViewHolder,它看起来像这样:

override val viewHolder: BaseViewHolder<ScorerView> = BaseViewHolder(ScorerView(context))

BaseViewHolder类:

class BaseViewHolder<out V : View>(val v: V) : RecyclerView.ViewHolder(v)

(到现在为止没什么有趣的)

我的ScorerView 是:

class ScorerView @JvmOverloads constructor(
        context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {

    init {
        LayoutInflater.from(context).inflate(R.layout.item_ranking, this, false)
    }

    fun configure(id: String, player: String, team: String, matchSet: String, points: String, pointsAvg: String) {
        idTextView.text = id
        playerTextView.text = player
        teamTextView.text = team
        matchSetTextView.text = matchSet
        pointsTextView.text = points
        pointsAvgTextView.text = pointsAvg
    }
}

问题是当我将false 传递给inflate 函数时(这没关系,因为RecyclerView 需要项目视图没有附加到根视图)然后我的小部件实例(例如idTextView)一片空白。否则,当我通过传递 true 或调用 addView(view) 手动将视图附加到 root 时,我会遇到崩溃,说创建时无法附加视图:

ViewHolder 视图在创建时不得附加。确保您没有将“true”传递给 LayoutInflater.inflate(..., boolean attachToRoot) 的 attachToRoot 参数

我的问题是:有可能吗?如果不是,为什么官方文档说可以手动创建视图?

【问题讨论】:

    标签: android android-recyclerview android-viewholder


    【解决方案1】:

    问题是您一遍又一遍地返回相同的视图。明确要求 onCreateViewHolder() 在每次调用时创建一个新视图

    文档说您可以手动创建视图,但这仍然意味着您每次运行 onCreateViewHolder() 时手动创建不同的视图。

    因此,因为您每次都在重复使用同一个视图,即您的应用调用onCreateViewHolder()次,该视图已附加到父视图。

    【讨论】:

    • 感谢您的回复。你是对的,我一遍又一遍地返回同一个对象。我进入了符号陷阱。不幸的是,它不能解决我的问题,因为小部件在第一个 onBindViewHolder 调用中仍然为空。我想补充一点,我的 ScorerView 类不是问题,因为当我在 Fragment 中使用 attachToRoot = false 手动创建它时,我会因 null 小部件而崩溃,但是当我将此参数设置为 true 时,一切都是好的,我可以正常使用了。
    • 当你在onCreateViewHolder() 中膨胀一个视图,然后将它传递给一个ViewHolder 构造函数时,将false 传递给attachToRoot 是可以的,因为回收器视图将为你完成附加。在您发布init { LayoutInflater.from(context).inflate(R.layout.item_ranking, this, false) } 的代码中,这个视图只是被丢弃了,因为您没有手动将它附加到任何东西上。
    • 其实我不明白,但我通过了attachToRoot = true,现在它正在工作。同时进行一些代码清理,我更改了我的.xml 文件名,所以我想IDE 肯定有什么问题,但我实际上不知道是什么。我在这个问题上花了很多时间,所以这很令人沮丧。无论如何,非常感谢您的回答,我会接受它,因为实际上您在我的代码中发现了一个错误 :)
    猜你喜欢
    • 1970-01-01
    • 2016-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多