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