RecyclerПросмотреть список элементов пустым в ItemTouchHelper.SimpleCallback - PullRequest
0 голосов
/ 11 марта 2020

RecyclerView должен показывать некоторым рабочим часам пользователей и позволять им редактировать / удалять их. Чтобы включить редактирование и удаление, я прикрепил ItemTouchHelper.SimpleCallback к RecyclerView, чтобы иметь смахивание для удаления и смахивание для редактирования . Сначала все это работало как очарование, но после внесения некоторых изменений в сетевой уровень он сломался странным образом.

Каждый раз, когда я пролистываю, адаптер , используемый при обратном вызове, имеет пустой список элементов , несмотря на отображаемые элементы. Если я нажимаю на элемент, все работает нормально. Я проверил с помощью отладчика, и адаптер, который используется onSwiped, является точно таким же экземпляром, что и адаптер, используемый действием.

Я попытался установить наблюдатель поля на shifts, но не повезло. Я попытался отладить каждый метод, который обращается к одному и тому же списку, никто его не очищает.

Вот Адаптер, я опустил некоторые методы, потому что они даже не достигнуты:

class UserActivityRecyclerViewAdapter constructor(
    private val context: Context,
    private val listener: UserActivityListener
) : RecyclerView.Adapter<UserActivityRecyclerViewAdapter.ViewHolder>(), SwipeActions {

    private val shifts = arrayListOf<Shift>()
    private val recentlyDeleted: Queue<Shift> = ArrayDeque()
    private val recentlyDeletedPosition: Queue<Int> = ArrayDeque()

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

        val context = parent.context
        val inflater = LayoutInflater.from(context)
        val recyclerViewItem = inflater.inflate(R.layout.item_user_activity, parent, false)
        return ViewHolder(recyclerViewItem)
    }

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

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {

        // setting view content
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int, payloads: MutableList<Any>) {
        if (payloads.isEmpty()) {
            onBindViewHolder(holder, position)
        } else {

            payloads.forEach { list ->

                (list as List<Any?>).forEach {
                 // check for specific changes in order to show a nicer animation than the default bubble
                }
            }
        }
    }

    override fun deleteItem(rootView: View, position: Int) {
        recentlyDeleted.add(shifts[position])
        recentlyDeletedPosition.add(position)
        shifts.removeAt(position)
        notifyItemRemoved(position)
        showUndoSnackbar(rootView)
    }

    private fun undoDelete() {
        val recDelPos = recentlyDeletedPosition.remove()
        shifts.add(recDelPos, recentlyDeleted.remove())
        notifyItemInserted(recDelPos)
    }

    override fun editItem(position: Int) {
        listener.onEdit(shifts[position], position)
        notifyItemChanged(position)
    }

    // this method is the only way for other classes to interact with content
    fun updateContent(newShifts: List<Shift>) {

        val sorted = newShifts.sortedByDescending { it.arrivalTime } // to be displayed
        val diffResult = DiffUtil.calculateDiff(ShiftsDiffCallback(this.shifts, sorted), true)

        shifts.clear()
        shifts.addAll(sorted)

        diffResult.dispatchUpdatesTo(this)
    }

    interface UserActivityListener {
        fun onDelete(shift: Shift, position: Int)
        fun onEdit(shift: Shift, position: Int)
    }

    class ViewHolder(itemView: View) :
        RecyclerView.ViewHolder(itemView)
}

А вот некоторые функции обратного вызова, я опустил onChildDraw, потому что он не имеет ничего общего с logi c:

class SwipeActionCallback(
    private val adapter: UserActivityRecyclerViewAdapter,
    private var rootView: View
) : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT or ItemTouchHelper.LEFT) {

 override fun onMove(
        recyclerView: RecyclerView,
        viewHolder: RecyclerView.ViewHolder,
        target: RecyclerView.ViewHolder
    ): Boolean {
        return false
    }

    // this is the moment when adapter.itemCount = 0 for the first time
    override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
        if (direction == ItemTouchHelper.RIGHT) {
            adapter.deleteItem(rootView, viewHolder.adapterPosition)
        } else {
            adapter.editItem(viewHolder.adapterPosition)
        }
    }
}

А вот как я инициализирую RecyclerView:

private fun initRecyclerView(activity: FragmentActivity) {
        mRecyclerView = user_activity_recycler_view
        mRecyclerView?.isNestedScrollingEnabled = false
        mRecyclerView?.layoutManager = LinearLayoutManager(context)
        val recyclerViewAdapter = UserActivityRecyclerViewAdapter(
            context!!,
            object : UserActivityRecyclerViewAdapter.UserActivityListener {

                override fun onDelete(shift: Shift, position: Int) {
                    deleteShift(shift)
                }

                override fun onEdit(shift: Shift, position: Int) {
                    editShift(shift)
                }
            }
        )
        mRecyclerView?.adapter = recyclerViewAdapter

        updateRecyclerView()

        val itemTouchHelper =
            ItemTouchHelper(
                SwipeActionCallback(
                    mRecyclerView?.adapter as UserActivityRecyclerViewAdapter,
                    activity.window.decorView.findViewById(R.id.layout_home_activity)
                )
            )
        itemTouchHelper.attachToRecyclerView(mRecyclerView)
    }

и как мне его обновить:

private fun updateRecyclerView() {
        (mRecyclerView?.adapter as UserActivityRecyclerViewAdapter)
            .updateContent(
                user!!.getUserActivity( // this returns a filtered list of shifts
                    timeManager.arrivalTime,
                    timeManager.exitTime
                )
            )
    }
...