繁体   English   中英

我们可以改变 textview 在同一个片段上吗?

[英]can we change textview being on same fragment?

我正在开发一个演示应用程序,每当我在回收器视图的同一项目中更改 edittext 的值时,我都必须更新 recyclerview 中项目的 texview。 以下是我的 rcv 适配器。

class RecyclerViewAdapterU (val dataList:ArrayList<ModelClass>): RecyclerView.Adapter<RecyclerViewAdapterU.ViewHolder>() {
    var _binding: UploadItemViewBinding? = null
    val binding get() = _binding!!
    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): RecyclerViewAdapterU.ViewHolder {

        val v =
            LayoutInflater.from(parent.context).inflate(R.layout.upload_item_view, parent, false)
        _binding = UploadItemViewBinding.bind(v)
        return ViewHolder(binding.root)
    }


    override fun onBindViewHolder(holder: ViewHolder, @SuppressLint("RecyclerView") position: Int) {


        bindItems(dataList[position])
        holder.getStock()
        holder.updateStockDetail()

    }
    fun bindItems(data: ModelClass) {

        binding.itemquant.text = data.item_quant
        binding.uploadItemName.text = data.item_name
        binding.uploadMfg.text = data.mfg
        binding.skuStock.setText(data.item_stock.toString())
        binding.skuCode.setText(data.sku_code)
    }


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


    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        var stockdetail = ArrayList<ModelClass>()

        fun getStock() {

            binding.skuStock.addTextChangedListener(object : TextWatcher {
                override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
                override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
                override fun afterTextChanged(editable: Editable) {
                    for (i in 0 until RecyclerViewAdapter.ob.dataSelected.size){
                        if (editable.toString().trim()!=""){
                            var x= editable.toString().trim().toInt()
                            RecyclerViewAdapter.ob.dataSelected[adapterPosition].item_stock=x
                        }
                    }


                }

            })
        }

        fun updateStockDetail(){
            binding.skuCode.addTextChangedListener(object : TextWatcher{
                override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
                override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {


                }
                override fun afterTextChanged(editable: Editable) {
                    if (editable.length==3){

                    var x:String
                    for (i in 0 until RecyclerViewAdapter.ob.dataSelected.size){
                        if (editable.toString().trim()!=""){
                            x=editable.toString().trim()
                            RecyclerViewAdapter.ob.dataSelected[adapterPosition].sku_code=x
                            println("$x in if")

                        }
                    }
                    println(RecyclerViewAdapter.ob.dataSelected[adapterPosition].sku_code)
                    getUpdatedDetails(RecyclerViewAdapter.ob.dataSelected[adapterPosition].sku_code)
                        for (i in stockdetail){
                            bindItems(i)

                            //binding.uploadItemName.text=i.item_name
                            println(i.item_name)
                        }
       
                }
                }

            })
        }


        fun getUpdatedDetails(skucode:String){
            val call: Call<List<ModelClass>>? =
                ApiClient.instance?.myApi?.getfromsku(skucode)!!
            call!!.enqueue(object : Callback<List<ModelClass>?> {
                override fun onResponse(
                    call: Call<List<ModelClass>?>,
                    response: Response<List<ModelClass>?>
                ) {
                    val skuDetails=response.body()

                    stockdetail.clear()
                    if (skuDetails != null) {
                        for (i in skuDetails){
                            println(i.item_name)
                            stockdetail.addAll(skuDetails)
                        }
                    }
                }

                override fun onFailure(call: Call<List<ModelClass>?>, t: Throwable) {
                }
            })
        }
    }
}

查看 updatestockdetail function。 不确定我是否以正确的方式做事..如果不正确,有人可以帮助我以正确的方式做事吗?

问题的详细解释。 此图像 B20 中的屏幕截图是 Bingo20gm 的 sku 代码。 同样,L20 用于 Lays20gm,所以如果我将 B20 更改为 L20,则显示 Bingo 20gm 的 textview 应更改为 Lays 20gm。 数据由 API 提供,我在 getupdateddetails() 中调用它,并将它们放在一个列表中。

这更像是一个代码审查问题,但我认为你过于复杂了。

当您使用RecyclerView (或任何列表小部件)时,您有三个部分:

  • 你的数据
  • 显示数据的东西(在这种情况下是RecyclerView
  • 获取数据并确定如何显示它的东西( Adapter

RecyclerView中,数据显示在称为ViewHolder的迷你布局中。 不是为每个项目创建一个,而是创建一个池,当ViewHolder滚动出视图时,它会被回收(重用)以显示新项目 - 这就是为什么它被称为RecyclerView (而不是ListView

因此,每个ViewHolder都是可以显示项目详细信息的东西,当onBindViewHolder时,适配器会确定如何使用视图持有者来表示您的数据- 例如设置文本、图像、颜色、检查状态等。你还可以在ViewHolder中粘贴一些变量并在绑定期间设置这些变量,因此您可以获得有关当前显示内容的更多信息 - 设置position变量很常见。 这样,您可以将一些代码放入ViewHolder中,以处理它当前表示的数据。


关键是,您可以使ViewHolder这个独立的组件:

  • 有一个EditText和一个TextView
  • 创建时在EditText上设置TextWatcher
  • 每当EditText内容更改时更新TextView

这都是ViewHolder内部的,它只是在自己的布局中连接组件


如果您需要ViewHolder推送一些信息(例如您输入的文本或“单击按钮”事件),您可能希望在您的适配器中放置一个 function 以便它可以调用:

fun updateThing(data: String, position: Int) {
    // update your data sources, do any validation, etc
    // call notifyDataSetChanged() or similar, if required
}

如果您的 ViewHolder 中有一个position变量(您在ViewHolder期间onBindViewHolder ),那么 VH 只需在调用 function 时传递它。 嘿,这是更新,我正在显示 position X,这是新数据。 那样的话,VH 只关心 UI 的东西,所有的数据逻辑都在适配器中保持独立——这可以做一些事情,比如决定列表是否需要更新。


这样做的另一个原因是适配器也处理来自其他来源的更新,例如您的 API 调用。 所以如果你所有的数据更新逻辑都在一个地方,由一件事处理,那就容易多了。 这样,无论更新的来源是什么,无论出于何种原因需要更新,都以相同的方式完成。 如果适配器决定数据已更改,并且显示需要更新,则通过正常方法发生 - 即onBindViewHolder被调用,您在RecyclerView上设置当前数据。 所以你可以得到这个事件链:

  • ViewHolder更新上的EditText
  • TextWatcher代码使用新数据调用适配器的updateThing function
  • 适配器存储新数据并强制显示更新
  • onBindViewHolder被调用并显示(现在更改的)数据
  • ViewHolderTextView设置为显示新数据

所以在这种情况下,您根本不需要直接修改TextView ,您只需更新数据,作为该过程的一部分,新数据就会显示出来。 因为这就是数据更改时应该发生的事情,无论是什么导致它发生变化。 而且您无需担心是什么原因造成的,您只需显示它!


这是一个很长的答案,我显然没有重写你的代码,但希望它能让你更好地了解它是如何工作的,以及如何分离和简化它们。 您的ViewHolder中有很多代码可以操作数据、在适配器上四处寻找、迭代其中的所有项目等 - 它实际上应该只显示内容并对 UI 事件做出反应。 处理数据是适配器的工作

我尝试重新使用您的代码,但有些事情没有意义,例如RecyclerViewAdapter.ob.dataSelected 你从哪里得到RecyclerViewAdapter实例?

因此,我在下面粘贴了一段我之前编写的适配器代码,它可以解决与您需要的完全相同的目的。

class RecyclerViewAdapter(
    val interactionListener: InteractionListener,
    val onTextChangedListener: OnTextChangedListener
) : RecyclerView.Adapter<RecyclerViewAdapter.OptionViewHolder>() {

    private val variantsList = ArrayList<VariantsItem>()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OptionViewHolder {
        val binding = SellVariantRowItemBinding.inflate(
            LayoutInflater.from(parent.context),
            parent,
            false
        )
        return OptionViewHolder(binding)
    }

    override fun onBindViewHolder(holder: OptionViewHolder, position: Int) {
        holder.bind(variantsList[position])
    }

    override fun getItemCount() = variantsList.size

    fun updateVariantsList(newList: ArrayList<VariantsItem>) {
        variantsList.clear()
        variantsList.addAll(newList)
        notifyDataSetChanged()
    }

    inner class OptionViewHolder(
        private val binding: SellVariantRowItemBinding
    ) : RecyclerView.ViewHolder(binding.root) {

        private var subVariant: String = ""

        @SuppressLint("SetTextI18n")
        fun bind(variantsItem: VariantsItem) {
            subVariant = variantsItem.subVariant

            binding.apply {
                binding.root.tag = "pos_$bindingAdapterPosition"
                sizeTv.text = "Size (${bindingAdapterPosition+1})"
                variantValue.text = variantsItem.variant
                subVariantValue.text = variantsItem.subVariant
                quantityET.setText(variantsItem.quantity.toString().takeIf { it != "0" }?:"1")
                sellingPriceET.setText(variantsItem.listingPrice.toString())
                marketPriceET.setText(variantsItem.labelPrice.toString())

                setOnClickListeners(variantsItem)
                setTextChangeListeners(variantsItem)

            }
        }

        private fun setTextChangeListeners(item: VariantsItem) {
            binding.apply {
                quantityET.addTextChangedListener {
                    if (it.toString().toIntOrNull() != null) {
                        onTextChangedListener.onQuantityChanged(
                            bindingAdapterPosition,
                            item.subVariant, item.variant,
                            it.toString()
                        )
                    }
                }

                marketPriceET.addTextChangedListener {
                    if (it.toString().toIntOrNull() != null) {
                        onTextChangedListener.onMarketPriceChanged(
                            bindingAdapterPosition,
                            item.subVariant,item.variant,
                            it.toString()
                        )
                    }
                }

                sellingPriceET.addTextChangedListener {
                    if (it.toString().toIntOrNull() != null){
                        onTextChangedListener.onSellingPriceChanged(
                            bindingAdapterPosition,
                            item.subVariant,item.variant,
                            it.toString()
                        )
                    }
                }
            }
        }

        private fun setOnClickListeners(variantsItem: VariantsItem) {
            binding.apply {
                deleteVariantBtn.setSafeOnClickListener {
                    interactionListener.onDeleteCard(variantsItem)
                }

                subVariantLayout.setSafeOnClickListener {
                    interactionListener.onChangeSubVariant(variantsItem)
                }
                variantLayout.setSafeOnClickListener {
                    interactionListener.onChangeVariant(variantsItem)
                }
                addNewVariant.setSafeOnClickListener {
                    it.pan()
                    interactionListener.onAddVariant(variantsItem.subVariant)
                }
            }
        }
    }

    interface InteractionListener{
        fun onChangeSubVariant(subToBeDeleted: VariantsItem)
        fun onChangeVariant(variant: VariantsItem)
        fun onDeleteCard(variant: VariantsItem)
        fun onAddVariant(subVariantValue: String)
    }

    interface OnTextChangedListener{
        fun onQuantityChanged(position: Int, subVariant: String, variant: String, quantity: String)
        fun onMarketPriceChanged(position: Int, subVariant: String, variant: String, price: String)
        fun onSellingPriceChanged(position: Int, subVariant: String, variant: String, price: String)
    }
}

有几点需要注意:

  1. 您不能有一个binding实例来处理回收站视图的所有项目。 为此,我们有ViewHolder
  2. 将您的绑定逻辑以及与 ViewHolder 中的每个单独项目相关的所有内容。 这就是它的目的。
  3. 尽量让你的适配器简单,只写表现逻辑。 将所有业务逻辑保留在适配器之外。
  4. 接口是你最好的朋友。 这支持第 3 点。让您的活动/片段实现这些接口并将实例传递给适配器构造函数,例如val variantsAdapter = RecyclerViewAdapter(this, this) 这将允许您在 Recycler View 适配器之外编写业务逻辑(包括上下文所需的语句,例如调用不同的活动或启动服务,或者在您的情况下,进行 API 调用)

如果您有任何问题,请随时与我们联系。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM