У меня вопрос об Android RecyclerView.State .
Я использую RecyclerView, как я могу использовать и связать его с RecyclerView.State?
Моя цель - сохранить позицию прокрутки RecyclerView .
У меня вопрос об Android RecyclerView.State .
Я использую RecyclerView, как я могу использовать и связать его с RecyclerView.State?
Моя цель - сохранить позицию прокрутки RecyclerView .
Как вы планируете сохранять последнюю сохраненную позицию с помощью RecyclerView.State
?
Вы всегда можете рассчитывать на хорошее состояние сохранения. Расширить RecyclerView
и переопределить onSaveInstanceState () и onRestoreInstanceState()
:
@Override
protected Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
LayoutManager layoutManager = getLayoutManager();
if(layoutManager != null && layoutManager instanceof LinearLayoutManager){
mScrollPosition = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
}
SavedState newState = new SavedState(superState);
newState.mScrollPosition = mScrollPosition;
return newState;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
super.onRestoreInstanceState(state);
if(state != null && state instanceof SavedState){
mScrollPosition = ((SavedState) state).mScrollPosition;
LayoutManager layoutManager = getLayoutManager();
if(layoutManager != null){
int count = layoutManager.getItemCount();
if(mScrollPosition != RecyclerView.NO_POSITION && mScrollPosition < count){
layoutManager.scrollToPosition(mScrollPosition);
}
}
}
}
static class SavedState extends android.view.View.BaseSavedState {
public int mScrollPosition;
SavedState(Parcel in) {
super(in);
mScrollPosition = in.readInt();
}
SavedState(Parcelable superState) {
super(superState);
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(mScrollPosition);
}
public static final Parcelable.Creator<SavedState> CREATOR
= new Parcelable.Creator<SavedState>() {
@Override
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
@Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
Обновить
Введено начиная с
recyclerview:1.2.0-alpha02
релизаStateRestorationPolicy
. Это мог бы быть лучший подход к данной проблеме.Эта тема была рассмотрена в средней статье разработчиков Android .
Кроме того, @ rubén-viguera поделился более подробной информацией в ответе ниже. https://stackoverflow.com/a/61609823/892500
Старый ответ
Если вы используете LinearLayoutManager, он поставляется с предварительно созданным api сохранения linearLayoutManagerInstance.onSaveInstanceState () и восстановлением api linearLayoutManagerInstance.onRestoreInstanceState (...)
При этом вы можете сохранить возвращенную посылку в своем другом штате. например,
, и восстановить положение с сохраненным состоянием. например,
Подводя итог, ваш окончательный код будет выглядеть примерно так:
Изменить: вы также можете использовать тот же API с GridLayoutManager, так как это подкласс LinearLayoutManager. Спасибо @wegsehen за предложение.
Изменить: помните, что если вы также загружаете данные в фоновом потоке, вам понадобится вызов onRestoreInstanceState в вашем методе onPostExecute / onLoadFinished для восстановления позиции при изменении ориентации, например
источник
RecyclerView
но не тогда , когда у вас естьViewPager
сRecycerView
на каждой странице.onCreateView
, а после загрузки данных. См. Ответ @Farmaker здесь.хранить
Восстановить
и если это не сработает, попробуйте
Положить в магазин
onPause()
и восстановить вonResume()
источник
lastFirstVisiblePosition
до0
после восстановления. Этот случай полезен, когда у вас есть фрагмент / действие, которое загружает разные данные в одинRecyclerView
, например, приложение проводника файлов.SwipeRefreshLayout
?RecyclerView
Я хотел сохранить позицию прокрутки Recycler View, когда уходил от своей активности в списке, а затем нажимал кнопку «Назад», чтобы вернуться назад. Многие решения этой проблемы были либо намного сложнее, чем требовалось, либо не работали для моей конфигурации, поэтому я решил поделиться своим решением.
Сначала сохраните состояние вашего экземпляра в onPause, как многие показали. Думаю, здесь стоит подчеркнуть, что эта версия onSaveInstanceState является методом из класса RecyclerView.LayoutManager.
Ключ к правильной работе - это убедиться, что вы вызываете onRestoreInstanceState после присоединения адаптера, как некоторые указывали в других потоках. Однако фактический вызов метода намного проще, чем многие указывали.
источник
Я устанавливаю переменные в onCreate (), сохраняю позицию прокрутки в onPause () и устанавливаю позицию прокрутки в onResume ()
источник
Вам больше не нужно сохранять и восстанавливать состояние самостоятельно. Если вы установите уникальный идентификатор в xml и recyclerView.setSaveEnabled (true) (true по умолчанию), система автоматически сделает это. Подробнее об этом: http://trickyandroid.com/saving-android-view-state-correctly/
источник
Все менеджеры компоновки, входящие в состав библиотеки поддержки, уже знают, как сохранять и восстанавливать положение прокрутки.
Положение прокрутки восстанавливается при первом проходе макета, что происходит при соблюдении следующих условий:
RecyclerView
RecyclerView
Обычно вы устанавливаете диспетчер компоновки в XML, поэтому все, что вам нужно сделать сейчас, это
RecyclerView
Вы можете сделать это в любое время, это не ограничено
Fragment.onCreateView
илиActivity.onCreate
.Пример: убедитесь, что адаптер подключен каждый раз при обновлении данных.
Сохраненная позиция прокрутки рассчитывается на основе следующих данных:
Поэтому вы можете ожидать небольшого несоответствия, например, если ваши элементы имеют разные размеры в портретной и альбомной ориентации.
RecyclerView
/ScrollView
/ Что нужно иметьandroid:id
для своего государства , чтобы спастись.источник
LinearLayoutManager.SavedState
: cs.android.com/androidx/platform/frameworks/support/+/…Вот мой подход к их сохранению и поддержанию состояния recyclerview во фрагменте. Сначала добавьте изменения конфигурации в родительскую активность, как показано ниже.
Затем в своем фрагменте объявите этот метод экземпляра
Добавьте ниже код в свой метод @onPause
Добавьте метод onConfigartionChanged, как показано ниже.
Этот подход решит вашу проблему. если у вас другой менеджер компоновки, просто замените верхний менеджер компоновки.
источник
Вот как я восстанавливаю позицию RecyclerView с помощью GridLayoutManager после вращения, когда вам нужно перезагрузить данные из Интернета с помощью AsyncTaskLoader.
Сделайте глобальную переменную Parcelable и GridLayoutManager и статическую финальную строку:
Сохранение состояния gridLayoutManager в onSaveInstance ()
Восстановить в onRestoreInstanceState
Затем, когда загрузчик извлекает данные из Интернета, вы восстанавливаете позицию recyclerview в onLoadFinished ()
.. конечно, вам нужно создать экземпляр gridLayoutManager внутри onCreate. Ура
источник
У меня было такое же требование, но решения здесь не совсем помогли мне перейти линию из-за источника данных для recyclerView.
Я извлекал состояние LinearLayoutManager RecyclerViews в onPause ()
Parcelable
state
сохраняетсяonSaveInstanceState(Bundle outState)
и снова извлекаетсяonCreate(Bundle savedInstanceState)
, когдаsavedInstanceState != null
.Однако адаптер recyclerView заполняется и обновляется объектом ViewModel LiveData, возвращаемым вызовом DAO в базу данных Room.
В конце концов я обнаружил, что восстановление состояния экземпляра непосредственно после установки данных в адаптере будет сохранять состояние прокрутки при поворотах.
Я подозреваю, что это связано либо с тем, что
LinearLayoutManager
состояние, которое я восстановил, было перезаписано, когда данные были возвращены вызовом базы данных, либо восстановленное состояние было бессмысленным для «пустого» LinearLayoutManager.Если данные адаптера доступны напрямую (т. Е. Не связаны с вызовом базы данных), то восстановление состояния экземпляра в LinearLayoutManager может быть выполнено после того, как адаптер установлен в recyclerView.
Различие между двумя сценариями удерживало меня целую вечность.
источник
На уровне 28 Android API я просто проверяю, что настроил свой метод
LinearLayoutManager
andRecyclerView.Adapter
in myFragment#onCreateView
, и все работает Just Worked ™ ️. Мне не нужно было ничего делатьonSaveInstanceState
илиonRestoreInstanceState
работать.Ответ Евгения Печанека объясняет, почему это работает.
источник
Начиная с версии 1.2.0-alpha02 библиотеки androidx recyclerView, она теперь управляется автоматически. Просто добавьте его с помощью:
И используйте:
Перечисление StateRestorationPolicy имеет 3 варианта:
Обратите внимание, что на момент этого ответа библиотека recyclerView все еще находится в alpha03, но альфа-фаза не подходит для производственных целей .
источник
Для меня проблема заключалась в том, что я каждый раз настраивал новый менеджер компоновки при смене адаптера, теряя позицию прокрутки очереди в recyclerView.
источник
Я просто хотел бы поделиться недавней проблемой, с которой я столкнулся с RecyclerView. Я надеюсь, что любой, кто сталкивается с такой же проблемой, выиграет.
Требования к моему проекту: Итак, у меня есть RecyclerView, в котором перечислены некоторые интерактивные элементы в моем основном действии (Activity-A). При щелчке по элементу отображается новое действие с подробностями об элементе (действие-B).
Я реализовал в файле манифеста то, что Activity-A является родительским для Activity-B, таким образом, у меня есть кнопка возврата или возврата на панель действий Activity-B.
Проблема: каждый раз, когда я нажимал кнопку «Назад» или «Домой» на панели действий Activity-B, Activity-A переходит в полный жизненный цикл действия, начиная с onCreate ().
Несмотря на то, что я реализовал onSaveInstanceState (), сохраняющий список адаптера RecyclerView, когда Activity-A запускает его жизненный цикл, saveInstanceState всегда имеет значение null в методе onCreate ().
Продолжая копаться в Интернете, я столкнулся с той же проблемой, но человек заметил, что кнопка «Назад» или «Домой» под устройством Anroid (кнопка «Назад / Домой по умолчанию») Activity-A не входит в жизненный цикл активности.
Решение:
Я включил кнопку "Домой" или "Назад" на Activity-B
В методе onCreate () добавьте эту строку supportActionBar? .SetDisplayHomeAsUpEnabled (true)
В методе overide fun onOptionsItemSelected () я проверил item.ItemId, по которому щелкают элемент, на основе идентификатора. Идентификатор кнопки возврата:
android.R.id.home
Затем реализуйте вызов функции finish () внутри android.R.id.home
Это завершит Activity-B и принесет Acitivy-A без прохождения всего жизненного цикла.
Для моих требований это пока лучшее решение.
источник
У меня была такая же проблема с небольшой разницей, я использовал привязку данных , и я устанавливал адаптер recyclerView и layoutManager в методах привязки.
Проблема заключалась в том, что привязка данных происходила после onResume, поэтому мой layoutManager сбрасывался после onResume, а это означает, что он каждый раз возвращался в исходное место. Поэтому, когда я перестал устанавливать layoutManager в методах адаптера привязки данных, он снова работает нормально.
источник
В моем случае я устанавливал RecyclerView
layoutManager
как в XML, так и в форматеonViewCreated
. Снятие присвоенияonViewCreated
исправлено.источник
Activity.java:
Почему я использую
OnSaveInstanceState()
вonPause()
средствах, при переключении на другое действие onPause будет вызываться. Он сохранит эту позицию прокрутки и восстановит позицию, когда мы вернемся из другого действия.источник