RecyclerView - оставаться на 0 позиции после notifiyItemInserted (0) - PullRequest
0 голосов
/ 24 января 2019

У меня есть чат в моем приложении, и я хочу, чтобы мой 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 все сделано?

1 Ответ

0 голосов
/ 24 января 2019

Вы можете использовать RecyclerView.AdapterDataObserver () и обрабатывать то, что вам нужно.

Создайте свой класс слушателя, который реализует RecyclerView.AdapterDataObserver ()

, и в конструкторе вашего адаптера вызовите registerAdapterDataObserver (ваш слушатель))

и затем обрабатывает ваши обратные вызовы.

См. RecyclerView.AdapterDataObserver

...