Diffutil asynclist Другой метод списка отправки не работает должным образом

Я реализую recyclerview внутри recyclerview, как показано на изображении ниже, и использую diffutilasynclistdiffer для управления изменениями в элементах списка.

Список карточек событий

Добавляем код фрагмента и адаптеров ниже.

Код CustomizeEventFragment:

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

Код CustomizeEventViewModel:

          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, когда действие для выбора торта, добавления элементов или удаления выбранных элементов выполняется для любой карточки события, внутри наблюдателя я вызываю метод списка отправки CustomizeEventAdapters и каждый раз передаю обновленный список. Таким образом, каждый раз, когда данные списка изменяются / обновляются, вызывается наблюдатель, но это заставляет весь recyclerview обновлять его пользовательский интерфейс, например notifydatasetchanged. Я думаю, что это происходит потому, что я инициализирую recyclerview и адаптер внутри наблюдателя.

Это вызывает проблему, если предположить, что я выполняю какое-либо действие с 3-й картой события, а затем после того, как наблюдатель получает удар для этих изменений, он заставляет весь recyclerview обновлять свой пользовательский интерфейс, а элементы в recyclerview отображаются с первой начальной позиции.

Я попытался удалить приведенный ниже код инициализации recyclerview и адаптера вне наблюдателя.

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

Но когда я это делаю, вызов только метода списка отправки customizeEventRecyclerAdapter внутри наблюдателя не обнаруживает / не обновляет пользовательский интерфейс recyclerview в измененный список. Метод Diffutilasynclistdiffer submitlist должен обрабатывать изменения, но я не могу понять, почему он не работает должным образом. Пожалуйста, укажите на любую ошибку, которую я делаю в моем коде фрагмента / адаптера или реализации модели представления.

0 ответов