【问题标题】:Android Recyclerview with editable elements not updating correctly with new element具有可编辑元素的 Android Recyclerview 未使用新元素正确更新
【发布时间】:2022-02-02 10:36:41
【问题描述】:

所以,我有一个 Recyclerview,其中每个元素都包含一个图标、一个 textview 和一个 textedit。

适配器如下所示:

class ZutatenSmallListAdaptermitEingabe internal constructor(
    context: Context, parent: NewRezeptActivity
) : RecyclerView.Adapter<ZutatenSmallListAdaptermitEingabe.ZutatenViewHolder>() {

    private val inflater: LayoutInflater = LayoutInflater.from(context)
    private var zutaten = emptyList<ZutatenData>()
    private var mengenedits = emptyList<RefZutatRezept>()
    private val context = context
    private val parent = parent



    inner class ZutatenViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val zutatenItemView: TextView = itemView.findViewById(R.id.textSmallZutat)
        val zutatenPicView: ImageView = itemView.findViewById(R.id.image_SmallZutat)
        var zutatenMengenedit : EditText = itemView.findViewById(R.id.textedit_menge)

    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ZutatenViewHolder {
        var itemView :View = inflater.inflate(R.layout.recyclerview_item_small_mitmengeeingabe, parent, false)
        return ZutatenViewHolder(itemView)
    }

    override fun onBindViewHolder(holder: ZutatenViewHolder, position: Int) {
        val current = zutaten[position]
        val curpos = position
        holder.zutatenItemView.text = current.zutname
        holder.zutatenPicView.setImageDrawable(ContextCompat.getDrawable(context, current.bild))
        holder.zutatenItemView.setOnClickListener {
                parent.removeZutat(zutaten[position])
        }
        var richtigmengenedit =  mengenedits.firstOrNull() {it.zutatid == current.zutatid}
        if( richtigmengenedit != null) {
            holder.zutatenMengenedit.setText(richtigmengenedit.menge)
        }
        holder.zutatenMengenedit.addTextChangedListener(object : TextWatcher {
            override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int){
                mengenedits[curpos].menge =  holder.zutatenMengenedit.text.toString()

            }
            override fun afterTextChanged(s: Editable?) {}

            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
    })
    }

    internal fun setZutaten(zutats: List<ZutatenData>) {
        this.zutaten = zutats
        var neueListe = emptyList<RefZutatRezept>()
        for(zut in zutaten){
            var element = mengenedits.firstOrNull(){it.zutatid == zut.zutatid}
            if( element!= null){
                neueListe += element
            }else{
                neueListe += RefZutatRezept( zut.zutatid, 0, "")
            }
        }
        mengenedits = neueListe
        notifyDataSetChanged()
    }

    override fun getItemCount(): Int = zutaten.size
}

我有一个列表“zutaten”,用于存储要显示的元素,还有另一个列表“mengenedits”,用于存储用户写入 textedit 的文本。

我还有两个函数可以在列表中添加和删除元素。然后用 setZutatem 设置新的 List。

当我添加或删除一个元素时,我仍然想在 textedit 中显示正确的文本。 但问题是当列表“zutaten”更新时,“mengedits”列表正确更改,但在 onBindViewHolder 函数中它以某种方式被搞砸了。第二个元素的文本显示在第一个元素的文本编辑中。

【问题讨论】:

  • 我无法确切知道发生了什么,但我认为您应该设置一些断点(尤其是在 TextWatcher 代码中)并对其进行调试,然后尝试以这种方式弄清楚发生了什么。此外,据我所知,addTextChangedListener 添加到 a listTextWatchers 获取更新的文本回调,并且您每次 @987654326 时都会创建并添加一个新回调@ 已绑定。这可能会导致一些古怪的行为
  • 还有你创建的TextWatchers 基本上更新mengenedits[currentPosition],对吧?但是 currentPosition 的值在创建 TextWatcher 时是固定的(curpos 变量在 onBindViewHolder 退出时超出范围,下次运行时是 Watcher 不知道的全新变量)。因此,如果特定的 ViewHolder 显示位置 0,它会创建一个更新 mengenedits[0]TextWatcher。如果相同的ViewHolder 被重复用于显示位置9,它仍然有编辑mengenedits[0] 的观察者,并且当你为9 调用setText 时触发
  • 对不起,如果这令人困惑,这有点难以描述!而且我不知道那里的实际行为会是什么,但这就是我要看的地方。老实说,我只是在ViewHolder 本身中设置TextWatcher(所以它只发生一次),并在ViewHolder 上设置curpos 一个属性,所以onBindViewHolder 可以设置它并且TextWatcher 可以参考给它

标签: android kotlin android-recyclerview


【解决方案1】:

所以我不知道问题是什么,但我已经解决了:

我只是添加和删除某些项目,因此我没有替换整个列表,而是删除或添加了特定项目,而不是调用 notifyDataSetChanged(),我只是调用了 notifyItemInserted 和 notifyItemRemoved

所以删除添加的函数如下所示:

    fun addZutat(zutat: ZutatenData){
        zutaten.add(zutat)
        mengenedits.add( RefZutatRezept( zutat.zutatid, 0, ""))
        notifyItemInserted(zutaten.size -1)
    }

    fun removeZutat(zutat: ZutatenData){
        val pos = zutaten.indexOf(zutat)
        zutaten.removeAt(pos)
        mengenedits.removeAt(pos)
        notifyItemRemoved(pos)
    }

注意:我还将列表更改为 MutableLists,因为我想调用 removeAt()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-09
    • 2023-03-23
    • 2018-05-07
    • 1970-01-01
    相关资源
    最近更新 更多