在 onCreateViewHolder 中创建的 ViewHolder 中手动创建的视图

use*_*282 7 android android-viewholder android-recyclerview

我想制作通用适配器,让我可以重用它。这就是为什么我决定不创建 view by inflating,而是将之前创建的自定义视图传递给ViewHolderin ListAdapter( RecyclerView) in onCreateViewHolder。根据其文档,它应该是可能的,因为它说:

您可以手动创建新视图也可以从 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)
    }
}
Run Code Online (Sandbox Code Playgroud)

AdapterConfig实现类负责创建ViewHolder,它看起来像这样:

override val viewHolder: BaseViewHolder<ScorerView> = BaseViewHolder(ScorerView(context))
Run Code Online (Sandbox Code Playgroud)

BaseViewHolder 班级:

class BaseViewHolder<out V : View>(val v: V) : RecyclerView.ViewHolder(v)
Run Code Online (Sandbox Code Playgroud)

(直到现在没什么有趣的)

我的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
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

Ben*_* P. 8

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

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

因此,因为您每次都重复使用相同的视图,所以您的应用程序第二次调用 时onCreateViewHolder(),该视图已经附加到父视图。