我正在開發一個演示應用程式,每當我在回收器視圖的同一專案中更改 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 功能。不確定我是否以正確的方式做事..如果不正確,有人可以幫助我以正確的方式做事嗎?
問題的詳細解釋。 此影像 B20 中的螢屏截圖 是 Bingo20gm 的 sku 代碼。同樣,L20 用于 Lays20gm,所以如果我將 B20 更改為 L20,顯示 Bingo 20gm 的 textview 應該更改為 Lays 20gm。資料由 API 傳遞,我在 getupdateddetails() 中呼叫它,并將它們放在一個串列中。
uj5u.com熱心網友回復:
這更像是一個代碼審查問題,但我認為你過于復雜了。
當您使用RecyclerView(或任何串列小部件)時,您有三個部分:
- 你的資料
- 顯示資料的東西(
RecyclerView在這種情況下是 a) - 獲取資料并計算出如何顯示它的東西 (the
Adapter)
在 a中,資料以稱為sRecyclerView的迷你布局顯示。ViewHolder不是為每個專案創建一個,而是創建一個池,當一個ViewHolder滾動出視圖時,它會被回收(重用)以顯示一個新專案 - 這就是為什么它被稱為 a RecyclerView(而不是 a ListView)
因此,每個ViewHolder都是可以顯示專案詳細資訊的東西,當onBindViewHolder被呼叫時,配接器會計算出如何使用視圖持有者來表示您的資料- 例如設定文本、影像、顏色、檢查狀態等。您還可以在系結中粘貼一些變數并在系結期間設定這些變數,因此您可以獲得有關當前顯示內容的更多資訊 - 設定變數很常見。這樣,您可以將一些代碼放入它當前表示的資料中。ViewHolderpositionViewHolder
關鍵是,您可以制作ViewHolder這個獨立的組件:
- 有一個
EditText和一個TextView TextWatcher在EditText創建時設定 aTextView每當EditText內容更改時更新
這都是內部的ViewHolder,它只是在自己的布局中連接組件
如果您需要ViewHolder推送一些資訊(例如您輸入的文本或“單擊按鈕”事件),您可能希望在配接器中放置一個可以呼叫的函式:
fun updateThing(data: String, position: Int) {
// update your data sources, do any validation, etc
// call notifyDataSetChanged() or similar, if required
}
如果您的(您在 期間設定的)中有一個position變數,那么 VH 只需要在呼叫函式時傳遞它。嘿,這是一個更新,我正在顯示位置 X,這是新資料。這樣,VH 只關心 UI 的東西,所有的資料邏輯都在配接器中保持獨立——這可以做一些事情,比如決定串列是否需要更新。ViewHolderonBindViewHolder
The other reason for doing that, is that the adapter handles updates from other sources too, like your API call. So it's much easier if all your data update logic is in one place, handled by one thing. That way, whatever the source of the update, whatever the reason is for needing an update, it's all done the same way. And if the adapter decides that the data has changed, and the display needs to update, that happens through the normal methods - i.e. onBindViewHolder gets called, where you set the current data on the RecyclerView. So you can get this chain of events:
EditTextonViewHolderupdatesTextWatchercode calls the adapter'supdateThingfunction with the new data- the adapter stores the new data and forces a display update
onBindViewHoldergets called and displays the (now changed) data- the
ViewHolder'sTextViewis set to show the new data
so in this case, you don't need to directly modify the TextView at all, you just update the data, and as part of that process the new data will just get displayed. Because that's what should happen when the data is changed, whatever caused it to change. And you don't need to worry about what caused it, you just display it!
That was a long answer and I obviously haven't rewritten your code, but hopefully it gives you a better idea of how this works and how you can separate things and simplify them. You have a lot of code in your ViewHolder that manipulates data, pokes around at the adapter, iterates over all the items in it etc. - it should really just display stuff and react to UI events. Messing with the data is the adapter's job
uj5u.com熱心網友回復:
我嘗試重新使用您的代碼,但有些事情沒有意義,例如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)
}
}
有幾點需要注意:
- 您不能有一個
binding實體來處理回收站視圖的所有專案。我們有ViewHolder這個目的。 - 將您的系結邏輯以及與 ViewHolder 中的每個單獨專案相關的所有內容。這就是它的目的。
- 盡量讓你的配接器簡單,只寫表現邏輯。將所有業務邏輯保留在配接器之外。
- 介面是你最好的朋友。這支持第 3 點。使您的活動/片段實作這些介面并將實體傳遞給 Adapter 建構式
val variantsAdapter = RecyclerViewAdapter(this, this)。這將允許您在 Recycler View 配接器之外撰寫業務邏輯(包括背景關系所需的陳述句,例如呼叫不同的活動或啟動服務,或者在您的情況下,進行 API 呼叫)
如果您有任何問題,請隨時與我們聯系。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/424648.html
