RecyclerView Items' values reset when scrolling down

风流意气都作罢 提交于 2020-12-06 16:47:38

问题


Here is the scenario of what I am trying to do: I am creating a RecyclerView that can add or remove one or more child item/fragment/view that has EditText(s) but....

Here is my problem: Whenever I scroll down in my RecyclerView, its items' value resets. I think the problem here is that the RecyclerView Adapter cannot bind or hold the values but I don't know where exactly is the problem in my code.

class StocksAdapter() : RecyclerView.Adapter<ViewHolder>() {


class StockFragmentHolder : ViewHolder {
    fun Double.format(digits: Int) = java.lang.String.format("%,.${digits}f", this)


    lateinit var numberOfShares: EditText;
    lateinit var buyPrice: EditText;
    lateinit var btnCompute: Button
    lateinit var btnRemove: Button
    lateinit var stockAveragePrice: TextView
    lateinit var stockTotalAmount: TextView
    private var savedStock : Stock? = null

    constructor(view: View) : super(view) {
        numberOfShares = view.findViewById(R.id.stockNumberOfShares)
        buyPrice = view.findViewById(R.id.stockBuyPrice)
        btnCompute = view.findViewById(R.id.btnCompute)
        btnRemove = view.findViewById(R.id.btnRemove)
        stockAveragePrice = view.findViewById(R.id.stockAveragePrice)
        stockTotalAmount = view.findViewById(R.id.stockTotalAmount)
    }


    fun populateView(stock: Stock, onStocksAdapterListener: OnStocksAdapterListener, position: Int) {

        if(savedStock == null || stock.buyPrice > 0 || stock.numberOfShares > 0) {
            savedStock = stock
        }

        this.buyPrice.setText(if (savedStock!!.buyPrice <= 0.0) "" else savedStock!!.buyPrice.toString())
        this.numberOfShares.setText(if (savedStock!!.numberOfShares <= 0.0) "" else savedStock!!.numberOfShares.toString())
        this.stockAveragePrice.text = "0"
        this.stockTotalAmount.text = "0"

        this.btnCompute.setOnClickListener(View.OnClickListener {

            var stock = Stock();

            stock.numberOfShares = this.numberOfShares.text.toString().toLongOrNull()
            stock.buyPrice = this.buyPrice?.text.toString().toDoubleOrNull()
            stock.sellPrice = 0.0


            if (stock.numberOfShares != null || stock.numberOfShares != 0L) {

                var buyTotalAmount: Double = 0.0;
                buyTotalAmount = StocksCalculator.calculateTotalSharesPrice(stock, StocksCalculator.TRANSACTION_FEE_BASE_VALUES, Constants.TRANSACTION_TYPE.TRANSACTION_TYPE_BUY)

                var averagePricePerShare = (buyTotalAmount / stock.numberOfShares)

                this.stockAveragePrice.text = averagePricePerShare.format(2);
                this.stockTotalAmount.text = "" + buyTotalAmount.format(2)

                onStocksAdapterListener.onStocksComputeButtonClicked(stock.numberOfShares, averagePricePerShare, buyTotalAmount, position)
            }
        })

        this.btnRemove.setOnClickListener(View.OnClickListener {
            onStocksAdapterListener.onStocksRemoveButtonClicked(position)
        })

    }
}


lateinit var onStocksAdapterListener: OnStocksAdapterListener;
lateinit var listStocks: ArrayList<Stock>

public constructor(listStocks: ArrayList<Stock>, onStocksAdapterListener: OnStocksAdapterListener) : this() {
    this.listStocks = listStocks
    this.onStocksAdapterListener = onStocksAdapterListener
    setHasStableIds(true)

}

override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): RecyclerView.ViewHolder {
    var itemView = LayoutInflater.from(parent?.getContext())
            .inflate(R.layout.fragment_stock, parent, false)
}

override fun getItemViewType(position: Int): Int {
    return position
}


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

override fun onBindViewHolder(holder: RecyclerView.ViewHolder?, position: Int) {
    var stock: Stock = listStocks.get(position)
    holder.populateView(stock, this.onStocksAdapterListener, position)
}


public interface OnStocksAdapterListener {
    public fun onStocksAddButtonClicked()

    public fun onStocksComputeButtonClicked(numberOfShares: Long?, averagePricePerShare: Double?, averageTotalAmount: Double?, position: Int)

    public fun onStocksRemoveButtonClicked(position: Int)
}

Here is how I create my recyclerView in my Fragment:

    val mLayoutManager = LinearLayoutManager(this.context)
    var recyclerView: RecyclerView = view.findViewById(R.id.recyclerView)

    val itemDecorator = DividerItemDecoration(context, DividerItemDecoration.VERTICAL)
    itemDecorator.setDrawable(ContextCompat.getDrawable(context, R.drawable.divider))
    recyclerView.addItemDecoration(itemDecorator)
    recyclerView.setLayoutManager(mLayoutManager)
    recyclerView.setItemAnimator(DefaultItemAnimator())
    recyclerView.adapter = stocksAdapter

I have tried disabling the setIsRecyclable of the ViewHolder but the problem still persists.

What is the best approach to prevent the RecyclerView to stop resetting the values? Or should I replace the RecyclerView with ListView?


回答1:


I found a workaround by increasing the cache size of the recyclerview. Just ensure that the cache size is good enough for your application.

code:

recyclerView.setItemViewCacheSize(int);



回答2:


As I have seen in your code you are trying to add an item just after the activity load. So when you scroll your activity then again it calls the onCreate activity and data is again load from the storage or network so load data in specific method or in OnActiviyt Result method.




回答3:


I don't know in your code what is savedStock or what do you use it for. But your populateView method doesn't work as intended.

If you only use this savedStock for rendering, remove it completely, otherwise, don't use it in the populateView.

In populateView depend on the stock passed according to the position you get to draw the values.

Your code should be something like

this.buyPrice.setText(if (stock!!.buyPrice <= 0.0) "" else stock!!.buyPrice.toString())
this.numberOfShares.setText(if (stock!!.numberOfShares <= 0.0) "" else stock!!.numberOfShares.toString())


来源:https://stackoverflow.com/questions/50328655/recyclerview-items-values-reset-when-scrolling-down

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!