У меня есть чат в моем приложении, и я хочу, чтобы мой RV оставался в позиции 0, когда приходит новое сообщение, и первая видимая позиция элемента равна 0, но новые сообщения добавляются над видимым в данный момент, но видимые элементы остаются втак что пользователь должен прокрутить, чтобы увидеть новое сообщение.
Мой адаптер был расширен с RecyclerView.Adapter<RecyclerView.ViewHolder>
, и я нашел небольшое хакерское решение, чтобы заставить его работать:
private suspend fun update(newItems: List<IChatItem>) {
var recyclerViewState: Parcelable? = null
if ((recyclerView?.layoutManager as LinearLayoutManager).findFirstCompletelyVisibleItemPosition() == 0) {
recyclerViewState = recyclerView?.layoutManager?.onSaveInstanceState()
}
val diffResult = withContext(Dispatchers.Default) {
DiffUtil.calculateDiff(Diff(this.currentItems, newItems))
}
diffResult.dispatchUpdatesTo(this)
recyclerViewState?.let {
recyclerView?.layoutManager?.onRestoreInstanceState(recyclerViewState)
}
}
Это экономитСостояние RV и после завершения работы DiffUtil восстановите его.Это сработало, но теперь я пытаюсь реализовать новый адаптер и расширить класс адаптера с ListAdapter
, потому что он запускает DiffUtil в другом потоке.Это работает хорошо, но проблема в том, что я не могу реализовать свое предыдущее решение здесь, просто оно не работает.
Я попытался сделать следующее:
override fun submitList(list: MutableList<IChatItem>?) {
var recyclerViewState: Parcelable? = null
if ((recyclerView?.layoutManager as LinearLayoutManager).findFirstCompletelyVisibleItemPosition() == 0) {
recyclerViewState = recyclerView?.layoutManager?.onSaveInstanceState()
}
super.submitList(list)
recyclerViewState?.let {
recyclerView?.layoutManager?.onRestoreInstanceState(recyclerViewState)
}
}
Но это не работаетбольше.У кого-нибудь есть решение?
PS: я нашел этот вопрос - Вставка элементов RecyclerView в нулевое положение - всегда оставаться прокрученным до верха , но я не думаю, что это лучшее решение для добавления пустых невидимых элементов в адаптерсписок.Есть еще идеи?
UPD : как я и думал - поскольку этот адаптер запускает DiffUtil в другом потоке, он восстанавливает состояние RV до того, как DiffUtil завершит свою работу.Этот код работает:
override fun submitList(list: List<IChatItem>?) {
var recyclerViewState: Parcelable? = null
if ((recyclerView?.layoutManager as LinearLayoutManager).findFirstCompletelyVisibleItemPosition() == 0) {
recyclerViewState = recyclerView?.layoutManager?.onSaveInstanceState()
}
super.submitList(list)
recyclerViewState?.let {
Handler().postDelayed(
{
recyclerView?.layoutManager?.onRestoreInstanceState(recyclerViewState)
}, 1000
)
}
}
Но, конечно, это не то, что я хочу.Есть ли способ определить, когда с DiffUtil все сделано?