【问题标题】:How to update serial number text in recyclerview items in real time如何实时更新recyclerview项目中的序列号文本
【发布时间】:2020-03-23 16:46:52
【问题描述】:

我有一个 RecyclerView,它在每个列表项的开头显示一系列数字,如下所示。

我通过获取项目在列表中的位置并添加一个来做到这一点。

onBindViewHolder

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    val item = getItem(position)
    holder.bind(item!!, clickListener)
    holder.numberTextView.text = position.plus(1).toString()
}

我希望在删除列表中的项目时实时更新数字。截至目前,当我删除 recyclerview 中的项目时,我得到一个如下所示的列表。我必须刷新布局以获取顺序编号列表。如何实时更新数字。

我的适配器

    class Adapter( 
       private val clickListener: ClickListener) :
ListAdapter<DataItems, Adapter.ViewHolder>(DiffCallback()) {

class DiffCallback : DiffUtil.ItemCallback<DataItems>() {
    override fun areItemsTheSame(oldItem: DataItems, newItem: DataItems): Boolean {
        return oldItem.itemId == newItem.itemId
    }

    @SuppressLint("DiffUtilEquals")
    override fun areContentsTheSame(oldItem: OrderSummary, newItem: OrderSummary): Boolean {
        return oldItem == newItem
    }
}

fun getItemAtPosition(position: Int): DataItems {
    return getItem(position)
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    val item = getItem(position)
    holder.bind(item!!, clickListener)
    holder.umberTextView.text = position.plus(1).toString()
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    return ViewHolder.from(parent)
}

class ViewHolder private constructor(val binding: ItemBinding) :
    RecyclerView.ViewHolder(binding.root) {

    val numberTextView = binding.orderItemListNumber

    fun bind(
        item: DataItems,
        clickListener: SummaryItemListener
    ) {
        binding.clickListener = clickListener
        binding.DataItems= item
        binding.executePendingBindings()
    }

    companion object {
        fun from(parent: ViewGroup): ViewHolder {
            val layoutInflater = LayoutInflater.from(parent.context)
            val binding =
                ItemBinding.inflate(layoutInflater, parent, false)
            return ViewHolder(binding)
        }
    }
}

}

我如何删除一个项目:

    override fun onSwiped(
        viewHolder: RecyclerView.ViewHolder, 
         direction: Int) {
            val position = viewHolder.adapterPosition
            val item = adapter.getItemAtPosition(position)

            if (direction == ItemTouchHelper.LEFT) {
                val toast: Toast =
                    Toast.makeText(
                        context,
                        "1 item removed: ${item.name}",
                        Toast.LENGTH_SHORT
                    )
                toast.setGravity(Gravity.CENTER, 0, 0)
                toast.show()
          viewModel.delete(item) // Method to delete item from database
         } 

ViewModel 中的删除方法

    fun delete(summary: OrderSummary) {
    uiScope.launch {
        deleteItem(summary)
        }
    }

    private suspend fun deleteItem(orderSummary: OrderSummary) {
       withContext(Dispatchers.IO) {
            database.delete(orderSummary)
        }
    }

【问题讨论】:

  • 删除一个item后,使用Adapter.notifyDataSetChanged();在你的情况下应该足够了。
  • 我已经尝试过了,但它不适用于 DiffUtil :(

标签: android android-studio kotlin android-recyclerview


【解决方案1】:

您需要通过从RecyclerView 发送位置来从列表中删除该项目,一旦您这样做,该项目的位置将被更新。

您可以通过使适配器可以看到您的类中的列表来做到这一点,因为它可以从中删除。

【讨论】:

    【解决方案2】:

    尝试使用项目索引而不是 onBindViewHolder() 中的位置,使其看起来像这样:

    override fun onBindViewHolder(holder: ViewHolder, 
    position: Int) {
        val item = getItem(position)
        val index = getCurrentList().indexOf(item)
        holder.bind(item!!, clickListener)
        holder.umberTextView.text = 
        index.plus(1).toString()
    }
    

    希望对你有帮助!

    【讨论】:

    • 它的工作方式或多或少与以前相同。如何观察索引的变化,例如使用观察者方法或 LiveData?
    • 向我们展示您的 deleteItem(或类似的)方法。
    • 你正在使用ViewModelListAdapter,所以你也应该使用LiveData,并在你的Activity/Fragment中观察它。每当您在onChanged() 中收到List&lt;DataItems&gt; 时,您都可以调用ListAdapter.submitList(),其余的都将由适配器处理。
    【解决方案3】:

    如果您使用notifyDataSetChanged(),则 RecyclerView 会重新绑定并重绘列表中的每个项目,包括屏幕上不可见的项目。这不是最优的。如果列表很大,则需要使用 DiffUtil。 如果我们使用 DiffUtil,那么当删除一个列表项时,你的 DiffUtil 看不到一些新旧项之间的区别。因此,onBindViewHolder(..) 不会为所有可见列表项调用。 因此,代码:

    holder.umberTextView.text = position.plus(1).toString()
    

    对于某些元素不起作用。

    可能的解决方案:

    @Entity(tableName = "data_item_table")
        data class DataItem(
        
            @PrimaryKey(autoGenerate = true)
            var itemId: Long = 0L,
           
            var fieldOne: Long = 0L,        
        
            // !!! This field is not stored in the database, but is filled in YoursViewModel
            @Ignore
            var sequentialNumber: Int = 0
        
        )
        
        //-------------------------
            
        class YoursViewModel(private val dataSource: YoursDatabaseDao) : ViewModel() {
        
            private val dataItemsWhereSequentialNumberIsZero = dataSource.getAllDataItems()
        
            // !!! Here we set the actual sequential number
            val dataItems =
                Transformations.map(dataItemsWhereSequentialNumberIsZero ) { dataItems ->    
                    var i = 0
                    dataItems.forEach {
                        it.sequentialNumber = ++i
                    }
                    dataItems
                }
        
            fun deleteById(dataItemId: Long) {
                viewModelScope.launch {
                    dataSource.deleteById(dataItemId)
                }
            }
        }
    
        //-------------------------
        @Dao
        interface YoursDatabaseDao {
    
            @Query("SELECT * FROM data_item_table ORDER BY itemId ASC")
            fun getAllDataItems(): LiveData<List<DataItem>>
        }
    

    在活动或片段中,订阅 LiveDate 数据项

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-05
      • 1970-01-01
      • 2015-12-04
      • 1970-01-01
      • 2018-11-03
      • 1970-01-01
      相关资源
      最近更新 更多