1

我正在 recyclerview 中实现 recyclerview ,如下图所示,并使用 diffutil asynclistdiffer 来管理列表元素中的更改。

活动卡片列表

在下面添加片段和适配器的代码。

自定义事件片段代码:

class CustomizeEventFragment : Fragment(){

private lateinit var mContext: Context
private lateinit var viewModel: CustomizeEventViewModel
private lateinit var customizeEventRecyclerAdapter: CustomizeEventRecyclerAdapter

companion object {
    fun newInstance() = CustomizeEventFragment()
}

override fun onAttach(context: Context) {
    super.onAttach(context)
    mContext = context
}

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                          savedInstanceState: Bundle?): View? {
    return inflater.inflate(R.layout.customize_event_fragment, container, false)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    Log.d("App", "Inside onviewcreated customize event fragment")
    viewModel = activity?.let { ViewModelProvider(it).get(CustomizeEventViewModel::class.java) }!!
    subscibeObservers()
}

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    Log.d("App", "Inside onactivity created of customize event fragment")

}

private fun subscibeObservers(){
    viewModel.customizeEventList.observe(viewLifecycleOwner, Observer {
        it?.let {
            rv_customizeEvents.apply {
                layoutManager = LinearLayoutManager(mContext)
                customizeEventRecyclerAdapter = CustomizeEventRecyclerAdapter(null, viewModel)
                adapter = customizeEventRecyclerAdapter
                setHasFixedSize(true)
            }
            customizeEventRecyclerAdapter.submitList(it)
        }
    })
}}

CustomizeEventRecyclerAdapter 代码:

class CustomizeEventRecyclerAdapter(private val interaction: Interaction? = null, val viewModel: CustomizeEventViewModel) :
    RecyclerView.Adapter<RecyclerView.ViewHolder>() {

val DIFF_CALLBACK = object : DiffUtil.ItemCallback<CustomizeEventModel>() {

    override fun areItemsTheSame(oldItem: CustomizeEventModel, newItem: CustomizeEventModel): Boolean {
        return oldItem.eventModel.eventName == newItem.eventModel.eventName
    }

    override fun areContentsTheSame(oldItem: CustomizeEventModel, newItem: CustomizeEventModel): Boolean {
        return oldItem ==newItem
    }

}
private val differ = AsyncListDiffer(this, DIFF_CALLBACK)

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {

    return ListViewHolder(
            LayoutInflater.from(parent.context).inflate(
                    R.layout.item_customized_event,
                    parent,
                    false
            ),
            interaction
    )
}

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
    when (holder) {
        is ListViewHolder -> {
            Log.d("App", "Inside onbindviewholder adapter")
            holder.bind(differ.currentList.get(position))
        }
    }
}

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

fun submitList(list: List<CustomizeEventModel>) {
    Log.d("App", "Inside submit list" + list.toString())
    differ.submitList(list)
}

inner class ListViewHolder
constructor(
        itemView: View,
        private val interaction: Interaction?
) : RecyclerView.ViewHolder(itemView), SelectedItemsRecyclerAdapter.Interaction {

    fun bind(item: CustomizeEventModel) = with(itemView) {

        itemView.tv_cardEventTitle.text = item.eventModel.eventName
        if (item.eventModel.member2.equals("")){
            itemView.tv_cardMembers.text = "Members: ${item.eventModel.member1}"
        }else{
            itemView.tv_cardMembers.text = "Members: ${item.eventModel.member1}, ${item.eventModel.member2}"
        }

        if (item.selectedCake.itemName.equals("")){
            itemView.btn_selectCake.setText("Select Cake")
        }else{
            itemView.btn_selectCake.setText(item.selectedCake.itemName)
        }

        itemView.btn_selectCake.setOnClickListener {
            val action: NavDirections = CustomizeEventFragmentDirections.actionCustomizeEventFragmentToBottomSheetCakeFragment(adapterPosition)
            Navigation.findNavController(it).navigate(action)
        }

        itemView.btn_addItem.setOnClickListener {
            val action: NavDirections = CustomizeEventFragmentDirections.actionCustomizeEventFragmentToBottomSheetAddItemsFragment(adapterPosition)
            Navigation.findNavController(it).navigate(action)
        }

        if (!item.selectedweight.equals("")){
            itemView.weightSelection.setText(item.selectedweight)
        }
        val weights: ArrayList<String> = ArrayList()
        val variants = item.selectedCake.variant
        for (i in variants){
            weights.add(i.weight)
        }

        val adspinner = ArrayAdapter(context, R.layout.item_citytext, weights)
        (itemView.weightSelection as? AutoCompleteTextView)?.setAdapter(adspinner)

        itemView.weightSelection.setOnItemClickListener { parent, view, position, id ->
            viewModel.updateSelectedWeight(parent.getItemAtPosition(position).toString(), adapterPosition)
        }

        val selectedItemsRecyclerAdapter: SelectedItemsRecyclerAdapter

        rv_itemList.apply {
            layoutManager = LinearLayoutManager(context.applicationContext)
            selectedItemsRecyclerAdapter = SelectedItemsRecyclerAdapter(this@ListViewHolder)
            adapter = selectedItemsRecyclerAdapter
            setHasFixedSize(true)
        }

        if (!item.selectedItems.isNullOrEmpty()){
            selectedItemsRecyclerAdapter.submitList(item.selectedItems.toList())
        }
    }

    override fun onItemRemoved(itemPosition: Int) {
        viewModel.removeSelectedItem(itemPosition, adapterPosition)
    }
}

interface Interaction {
    fun onItemSelected(position: Int)
}}

如附加的屏幕截图所示,当单击添加项目按钮时,另一个适配器被调用以设置选定项目的列表,我们也可以在单击“X”按钮时删除这些项目。SelectedItemsRecyclerAdapter 代码:

class SelectedItemsRecyclerAdapter(private val interaction: Interaction? = null) :
RecyclerView.Adapter<RecyclerView.ViewHolder>() {

val DIFF_CALLBACK = object : DiffUtil.ItemCallback<ProductModel>() {

    override fun areItemsTheSame(oldItem: ProductModel, newItem: ProductModel): Boolean {
        return oldItem.itemName == newItem.itemName
    }

    override fun areContentsTheSame(oldItem: ProductModel, newItem: ProductModel): Boolean {
        return oldItem == newItem
    }

}
private val differ = AsyncListDiffer(this, DIFF_CALLBACK)

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {

    return ListViewHolder(
        LayoutInflater.from(parent.context).inflate(
            R.layout.item_selected_items,
            parent,
            false
        ),
        interaction
    )
}

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
    when (holder) {
        is ListViewHolder -> {
            holder.bind(differ.currentList.get(position))
        }
    }
}

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

fun submitList(list: List<ProductModel>) {
    differ.submitList(list)
}

inner class ListViewHolder
constructor(
    itemView: View,
    private val interaction: Interaction?
) : RecyclerView.ViewHolder(itemView) {

    fun bind(item: ProductModel) = with(itemView) {

        itemView.tv_itemName.text = item.itemName
        itemView.iv_removeItem.setOnClickListener {
            interaction?.onItemRemoved(adapterPosition)
        }
    }
}

interface Interaction {
    fun onItemRemoved(itemPosition: Int)
}}

自定义事件视图模型代码:

    class CustomizeEventViewModel(application: Application) : AndroidViewModel(application) {
   var customizeEventList = MutableLiveData<List<CustomizeEventModel>>()

    fun updateCustomizeEventList(selectedEvents: List<EventModel>){
        val _customizeEventList: MutableList<CustomizeEventModel> = mutableListOf()

        for (item in selectedEvents){
            val _customizeEventModel = CustomizeEventModel(item)
            _customizeEventList.add(_customizeEventModel)
        }

        customizeEventList.value = _customizeEventList.toList()
    }

    fun updateSelectedCake(model: ProductModel, position: Int){
        val _customizeEventList: MutableList<CustomizeEventModel>? = customizeEventList.value as MutableList<CustomizeEventModel>?

        val customizeEventModel: CustomizeEventModel = _customizeEventList?.get(position)!!
        customizeEventModel.selectedCake = model

        _customizeEventList.set(position, customizeEventModel)
        customizeEventList.value = _customizeEventList.toList()
    }

    fun updateSelectedWeight(weight: String, adPosition: Int){
        val _customizeEventList: MutableList<CustomizeEventModel>? = customizeEventList.value as MutableList<CustomizeEventModel>?

        val customizeEventModel: CustomizeEventModel = _customizeEventList?.get(adPosition)!!
        customizeEventModel.selectedweight = weight

        _customizeEventList.set(adPosition, customizeEventModel)
        customizeEventList.value = _customizeEventList.toList()
    }

    fun updateSelectedItem(item: ProductModel, position: Int){
        val _customizeEventList: MutableList<CustomizeEventModel>? = customizeEventList.value as MutableList<CustomizeEventModel>?

        val itemList: ArrayList<ProductModel> = _customizeEventList?.get(position)?.selectedItems!!
        itemList.add(item)

        val customizeEventModel: CustomizeEventModel = _customizeEventList.get(position)
        customizeEventModel.selectedItems = itemList

        _customizeEventList.set(position, customizeEventModel)
        customizeEventList.value = _customizeEventList.toList()
    }

    fun removeSelectedItem (itemPosition: Int, adPosition: Int){
        val _customizeEventList: MutableList<CustomizeEventModel>? = customizeEventList.value as MutableList<CustomizeEventModel>?

        val itemList: ArrayList<ProductModel> = _customizeEventList?.get(adPosition)?.selectedItems!!
        itemList.removeAt(itemPosition)

        val customizeEventModel: CustomizeEventModel = _customizeEventList.get(adPosition)
        customizeEventModel.selectedItems = itemList

        _customizeEventList.set(adPosition, customizeEventModel)
        customizeEventList.value = _customizeEventList.toList()

    }}

问题描述: 在 CustomizeEventFragment 中,当对任何事件卡执行 Select cake、Add items 或 Remove selected Items 的操作时,然后在观察者内部我调用 CustomizeEventAdapters submitlist 方法并每次都传递更新的列表。因此,每当列表数据更改/更新时,都会调用观察者,但这会导致整个回收视图更新它的 UI,如 notifydatasetchanged。我认为这是因为我正在初始化观察者内部的 recyclerview 和适配器。

当假设我对第三个事件卡执行任何操作时,这会导致问题,然后在观察者因该更改而受到打击后,它会导致整个 recyclerview 更新其 UI 并且 recyclerview 中的项目从第一个初始位置显示。在 recyclerview 更新后,它应该保持在第 3 个事件卡位置。

我尝试在观察者之外删除以下 recyclerview 和适配器初始化代码

rv_customizeEvents.apply {
                layoutManager = LinearLayoutManager(mContext)
                customizeEventRecyclerAdapter = CustomizeEventRecyclerAdapter(null, viewModel)
                adapter = customizeEventRecyclerAdapter
                setHasFixedSize(true)
            }

但是当我这样做时,仅在观察者内部调用 customizeEventRecyclerAdapter submitlist 方法不会检测/更新 recyclerview UI 以更改列表。Diffutil asynclistdiffer submitlist 方法应该处理更改,但我无法理解为什么它没有按预期工作。请指出我在片段/适配器代码或视图模型实现中犯的任何错误。

4

0 回答 0