Значения элементов RecyclerView сбрасываются при прокрутке вниз - PullRequest
0 голосов
/ 14 мая 2018

Вот сценарий того, что я пытаюсь сделать: я создаю RecyclerView, который может добавить или удалить один или несколько дочерних элементов / фрагментов / представлений, которые имеют EditText (s), но ....

Вот моя проблема: всякий раз, когда я прокручиваю вниз в моем RecyclerView, значение его элементов сбрасывается. Я думаю, что проблема здесь в том, что Адаптер RecyclerView не может связывать или хранить значения, но я не знаю, где именно проблема в моем коде.

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)
}

Вот как я создаю свой переработчикПросмотр в моем фрагменте:

    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

Я попытался отключить setIsRecyclable ViewHolder, но проблема все еще сохраняется.

Каков наилучший подход для предотвращения переустановки значений RecyclerView? Или я должен заменить RecyclerView на ListView?

Ответы [ 3 ]

0 голосов
/ 14 мая 2018

Я нашел обходной путь, увеличив размер кэша в окне повторного просмотра. Просто убедитесь, что размер кеша достаточно хорош для вашего приложения.

код:

recyclerView.setItemViewCacheSize(int);
0 голосов
/ 14 мая 2018

Я не знаю в вашем коде, что такое savedStock или для чего вы его используете.Но ваш метод populateView не работает должным образом.

Если вы используете этот savedStock только для рендеринга, удалите его полностью, в противном случае, не используйте его в populateView.

В populateView зависит от stock, переданного в соответствии с позицией, которую вы получаете для рисования значений.

Ваш код должен быть примерно таким:

this.buyPrice.setText(if (stock!!.buyPrice <= 0.0) "" else stock!!.buyPrice.toString())
this.numberOfShares.setText(if (stock!!.numberOfShares <= 0.0) "" else stock!!.numberOfShares.toString())
0 голосов
/ 14 мая 2018

Как я видел в вашем коде, вы пытаетесь добавить элемент сразу после загрузки активности.Поэтому, когда вы прокручиваете свою деятельность, затем она снова вызывает операцию onCreate, и данные снова загружаются из хранилища или сети, поэтому загружайте данные определенным методом или в методе результата OnActiviyt.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...