【问题标题】:Android RecyclerView onBindViewHolder Called Twice (first time when adapter created)Android RecyclerView onBindViewHolder Called Twice(适配器创建时第一次)
【发布时间】:2019-04-17 17:33:27
【问题描述】:

我有简单的 RecyclerViewAdapter 类:

class TariffsCardAdapter(context: Context, tariffCardItems: List<ItemsItem?>?) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

   private var context: Context? = null
   private var tariffCardItems: ArrayList<ItemsItem?>? = null

    init {
      this.context=context
      this.tariffCardItems=tariffCardItems as ArrayList<ItemsItem?>
    }

   override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
       val view = LayoutInflater.from(parent.context).inflate(R.layout.layout_tariff_card_items, parent, false)
       return TariffsCardAdapterViewHolder(view)
   }

   override fun getItemCount(): Int {
       return tariffCardItems!!.size
   }//getItemCount ends

   override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {

     val viewHolder = holder as TariffsCardAdapterViewHolder
     Log.e("posX","pos:::".plus(position))
   }

   private inner class TariffsCardAdapterViewHolder : RecyclerView.ViewHolder {
      var text: TextView? = null
      constructor(row: View) : super(row) {
         text= row.findViewById(R.id.text) as TextView
      }
   }
}

现在假设我的 tariffCardItems: List 在列表中只有 5 个我想显示的项目!

问题是当适配器第一次被实例化时; onBindViewHolder 方法调用了两次!

以便日志值打印为:

pos:::0

pos:::1

pos:::0

pos:::1

这意味着我的回收站视图位置将是1! 并且第一个视图将使用 list item at 1 index 创建,这是错误的,应该是 0

简单来说,recycler 视图的第一个子视图是由 1 个位置值创建的,这是错误的

谁能帮我弄清楚我做错了什么

提前致谢和问候

【问题讨论】:

  • 不清楚是什么问题。 “回收站视图的第一个孩子是由错误的 1 个位置值创建的”——不,第一个位置是 0。我不知道你为什么认为它是 1,但是RecyclerView 会调用一些Adapter 方法不确定的次数,没有保证的顺序,同时它正在设置自己。您不应该将其用作任何类型的索引。
  • 是的,recyclerView 可能会以不确定的方式调用绑定方法。我不明白,为什么这是一个问题。 @Java Nerd 你能详细说明一下吗?

标签: android kotlin android-recyclerview


【解决方案1】:

这仅仅是因为您在代码中调用适配器 2,recyclerview 的 bindviewholder 应该用来绑定数据而不是调用 viewholder。

class TariffsCardAdapter(context: Context, tariffCardItems: List<ItemsItem?>?) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

   private var context: Context? = null
   private var tariffCardItems: ArrayList<ItemsItem?>? = null

    init {
      this.context=context
      this.tariffCardItems=tariffCardItems as ArrayList<ItemsItem?>
    }

   override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
       val view = LayoutInflater.from(parent.context).inflate(R.layout.layout_tariff_card_items, parent, false)
       return TariffsCardAdapterViewHolder(view)
   }

   override fun getItemCount(): Int {
       return tariffCardItems!!.size
   }//getItemCount ends

   override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {

                //bind data
   }

   private inner class TariffsCardAdapterViewHolder : RecyclerView.ViewHolder {
      var text: TextView? = null
      constructor(row: View) : super(row) {
         text= row.findViewById(R.id.text) as TextView
      }
   }
}

例如你的适配器应该是这样的

class CustomAdapter(val userList: ArrayList<User>) : RecyclerView.Adapter<CustomAdapter.ViewHolder>() {

    //this method is returning the view for each item in the list
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomAdapter.ViewHolder {
        val v = LayoutInflater.from(parent.context).inflate(R.layout.list_layout, parent, false)
        return ViewHolder(v)
    }

    //this method is binding the data on the list
    override fun onBindViewHolder(holder: CustomAdapter.ViewHolder, position: Int) {
        holder.bindItems(userList[position])
    }

    //this method is giving the size of the list
    override fun getItemCount(): Int {
        return userList.size
    }

    //the class is hodling the list view
    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

        fun bindItems(user: User) {
            val textViewName = itemView.findViewById(R.id.textViewUsername) as TextView
            val textViewAddress  = itemView.findViewById(R.id.textViewAddress) as TextView
            textViewName.text = user.name
            textViewAddress.text = user.address
        }
    }
}

您的代码中的这个方法调用了两次

 val viewHolder = holder as TariffsCardAdapterViewHolder
     Log.e("posX","pos:::".plus(position))

【讨论】:

  • 我想从模型中获取用户位置,我该怎么做?
  • 问题是,我必须从列表中获取项目,然后将项目绑定到 ui
  • 简单地转换和分配一个方法参数不会导致该方法被调用的次数出乎意料。这真的没有任何意义。
猜你喜欢
  • 2016-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-12
  • 2019-01-15
  • 1970-01-01
  • 2016-10-26
相关资源
最近更新 更多