Recycler查看数据回收

问题描述 投票:0回答:3

我正在android中开发一个电子商务应用程序,我使用Recyclerview来显示产品。每张卡上都有一个计数器可以增加/减少数量。

我的适配器代码:

class testadapter(
    private val context: Context,
    private val todaylist: ArrayList<TodaydealItem>
) :
    RecyclerView.Adapter<testadapter.MyView>() {

    class MyView(itemView: View) : RecyclerView.ViewHolder(itemView) {
        var prodid: TextView = itemView.findViewById(R.id.prodid)
        var qty: EditText = itemView.findViewById(R.id.qty)
        var sub: Button = itemView.findViewById(R.id.sub)
        var add: Button = itemView.findViewById(R.id.add)

    }

    private val quantityMap: HashMap<String, Int> = HashMap()
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyView {
        val itemView = LayoutInflater.from(parent.context)
            .inflate(R.layout.testlayout, parent, false)
        return MyView(itemView)
    }

    override fun onBindViewHolder(holder: MyView, position: Int) {
        val currentItem = todaylist[position]
        val resources = context.resources
        val producturl =
            resources.getString(R.string.domain_url) + "api/v2/products/" + currentItem.id
        holder.prodid.text = currentItem.id
        val quantity = quantityMap[currentItem.id] ?: 1
        holder.qty.setText(quantity.toString())

        holder.add.setOnClickListener {
            val currcount = holder.qty.text.toString()
            val currcountasnum: Int? = currcount.toIntOrNull()
            val stringRequest = StringRequest(
                Request.Method.GET,
                producturl,
                { s: String? ->
                    try {
                        val jsonObject = JSONObject(s.toString())
                        val dataArray = jsonObject.getJSONArray("data")

                        if (dataArray.length() > 0) {
                            val dataObject = dataArray.getJSONObject(0)

                            if (dataObject.has("current_stock")) {
                                val currentStock = dataObject.getInt("current_stock")
                                if (currcountasnum!! < currentStock) {
                                    holder.qty.setText((currcountasnum + 1).toString())
                                } else {
                                    Toast.makeText(
                                        context,
                                        "Maximum Stock Reached!",
                                        Toast.LENGTH_LONG
                                    ).show()
                                }
                            }
                        }

                    } catch (e: JSONException) {
                        e.printStackTrace()
                    }
                }
            ) { volleyError: VolleyError ->
                Toast.makeText(context, volleyError.message, Toast.LENGTH_LONG).show()
            }

            val requestQueue = Volley.newRequestQueue(context)
            requestQueue.add(stringRequest)
        }
        holder.sub.setOnClickListener {

            val currcount = holder.qty.text.toString()
            val currcountasnum: Int? = currcount.toIntOrNull()
            if (currcountasnum!! > 1) {
                holder.qty.setText((currcountasnum - 1).toString())
            } else {
                holder.qty.setText((currcountasnum - 1).toString())
            }

        }

    }

    override fun getItemCount(): Int {
        return todaylist.size
    }
}

问题是,当我通过增加计数器添加一些项目时,如果滚动它会自动返回到 0。有什么办法可以阻止这种情况并保持数量不变吗? sample image here

我在没有哈希图的情况下尝试过。保留数据。但是,在这种方法中,不止一种产品的数量会发生变化,甚至无需触及它们。

android kotlin android-recyclerview
3个回答
1
投票

我认为你只需通过调用

holder.qty.setText()
来更新ViewHoler上的数据,所以当滚动时onBindViewHolder将从
quantityMap
获取值并重新渲染

您应该更新

todaylist
并调用notifyItemChanged来重新渲染此视图持有者。我认为不需要使用HashMap来存储数量,应该只使用一个集合来加载列表数据,可以将字段数量创建到
todayList

的项目中
override fun onBindViewHolder(holder: MyView, position: Int) {
  //...
  holder.add.setOnClickListener {
     if (currcountasnum!! < currentStock) {
         todaylist[position].quantity = (currcountasnum + 1).toString()
         notifyItemChanged(position)
     }
   }
}

0
投票

由于 MVC 的规则,我不会在适配器内添加任何实际的单击侦听器。我所拥有的是在适配器内部调用的回调,并且调用函数会监听。

所以在适配器内部,我有类似的东西:

class SomeAdapter(val itemLst: MutableList<ItemModel>, val ctx: FragmentActivity) : RecyclerView.Adapter<SomeAdapter.ViewHolder>(){
    private lateinit var binding: AdapterItemBinding
    var onItemClick: ((ItemModel) -> Unit)? = null
    var onCloseClick: ((ItemModel, Int) -> Unit)? = null

    ...usual boiler plate
    
    override fun onBindViewHolder(holder: SomeAdapter.ViewHolder, position: Int) {
        val item = itemLst[position]
        holder.bind(item)
    }
    
    inner class ViewHolder(private val binding: AdapterSocketNotifBinding) :
        RecyclerView.ViewHolder(binding.root) {

        fun bind(item: ItemModel){
            binding.item = item
            
            //the important part for this question
            binding.someView.setOnClickListener{
                onCloseClick?.invoke(itemLst[adapterPosition], adapterPosition)
            }
        }
        
        //and this
        init {
            itemView.setOnClickListener {
                onItemClick?.invoke(itemLst[adapterPosition])
            }
        }
    }
}

然后在调用方,无论您在何处实例化此适配器:

itemAdapter.onCloseClick = { it, pos ->
    run {
        //do whatever you want here
    }
}

对于单参数点击监听器来说,就简单多了

itemAdapter.onClick = {
    //the variable it would automatically be equal to SomeItem
}

我知道这个答案看起来很复杂,但我想展示的是一种让您可以轻松访问

Fragment
Activity
变量的方法,这样您就不必担心如何更新您的适配器可能无法轻松访问的变量。


0
投票

您必须将计数器值存储在列表的模型类中,因此每当您从

onBindViewHolder()
中获取值时,它都会获得正确的值并且不会重置计数器。是的,当您更改点击计数器时,您必须执行
notifyItemChanged(position)

© www.soinside.com 2019 - 2024. All rights reserved.