RecyclerView хранить / восстанавливать состояние между действиями
Я перевожу свои ListViews в RecyclerViews. При просмотре списков я использовал общую технику, описанную здесь, чтобы сохранить и восстановить позицию прокрутки между действиями.
Как сделать то же самое с RecyclerViews? RecyclerView.onSaveInstanceState()
кажется protected
доступ, поэтому не может быть использован напрямую.
9 ответов
Итак, чтобы ответить на мой собственный вопрос. Насколько я понимаю, поскольку они разъединили код макета и код повторного использования представления (таким образом, имя), компонент, отвечающий за сохранение состояния макета (и его восстановление), теперь является LayoutManager
используется в вашем обзоре переработчика.
Таким образом, для сохранения состояния вы используете тот же шаблон, но в менеджере макета, а не в представлении реселлера:
protected void onSaveInstanceState(Bundle state) {
super.onSaveInstanceState(state);
// Save list state
mListState = mLayoutManager.onSaveInstanceState();
state.putParcelable(LIST_STATE_KEY, mListState);
}
Восстановить состояние в onRestoreInstanceState()
:
protected void onRestoreInstanceState(Bundle state) {
super.onRestoreInstanceState(state);
// Retrieve list state and list/item positions
if(state != null)
mListState = state.getParcelable(LIST_STATE_KEY);
}
Затем обновите LayoutManager (я делаю в onResume()
):
@Override
protected void onResume() {
super.onResume();
if (mListState != null) {
mLayoutManager.onRestoreInstanceState(mListState);
}
}
Я нашел лучшее решение - это решение имеет следующие преимущества:
- Состояние RecyclerView сохраняется и восстанавливается при повороте телефона
- Состояние RecyclerView сохраняется и восстанавливается при возврате к действию с RecyclerView (которое не было уничтожено во время отображения другого действия - это означает, что
onRestoreInstanceState()
не называется!!)
КОД
public class ActivityItemList extends AppCompatActivity
{
private final String KEY_RECYCLER_STATE = "recycler_state";
private RecyclerView mRecyclerView;
private static Bundle mBundleRecyclerViewState;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);//set to whatever layout name you have
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);//set to whatever view id you use
// don't forget to set your adapter
}
@Override
protected void onPause()
{
super.onPause();
// save RecyclerView state
mBundleRecyclerViewState = new Bundle();
Parcelable listState = mRecyclerView.getLayoutManager().onSaveInstanceState();
mBundleRecyclerViewState.putParcelable(KEY_RECYCLER_STATE, listState);
}
@Override
protected void onResume()
{
super.onResume();
// restore RecyclerView state
if (mBundleRecyclerViewState != null) {
Parcelable listState = mBundleRecyclerViewState.getParcelable(KEY_RECYCLER_STATE);
mRecyclerView.getLayoutManager().onRestoreInstanceState(listState);
}
}
}
Используйте этот код в onPause()
а также onResume()
сохранить и восстановить положение прокрутки
private Parcelable recyclerViewState;
recyclerViewState = mrecyclerView.getLayoutManager().onSaveInstanceState();//save
mrecyclerView.getLayoutManager().onRestoreInstanceState(recyclerViewState);//restore
Это мое решение, оно восстанавливает как предметы, так и позицию RecyclerView
1) сохранить состояние представления переработчика в методе onSaveInstanceState
@Override
protected void onSaveInstanceState(Bundle outState) {
Parcelable listState = myRecyclerView.getLayoutManager().onSaveInstanceState();
// putting recyclerview position
outState.putParcelable(SAVED_RECYCLER_VIEW_STATUS_ID, listState);
// putting recyclerview items
outState.putParcelableArrayList(SAVED_RECYCLER_VIEW_DATASET_ID,mDataset);
super.onSaveInstanceState(outState);
}
2) Проверьте Bundle сохраненного экземпляра в методе onCreate
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState==null){
getRemoteData(); // No saved data, get data from remote
}else{
restorePreviousState(); // Restore data found in the Bundle
}
}
3) Восстановите данные просмотра переработчика, если экран был повернут
public void restorePreviousState(){
// getting recyclerview position
mListState = mSavedInstanceState.getParcelable(SAVED_RECYCLER_VIEW_STATUS_ID);
// getting recyclerview items
mDataset = mSavedInstanceState.getParcelableArrayList(SAVED_RECYCLER_VIEW_DATASET_ID);
// Restoring adapter items
mAdapter.setItems(mDataset);
// Restoring recycler view position
mRvMedia.getLayoutManager().onRestoreInstanceState(mListState);
}
Я знаю, что опаздываю, но все же, если это поможет!
Сохранение позиции просмотра ресайклера намного проще, чем то, что сделали другие ответы.
Вот как вы можете это сделать
Сначала создайте переменную-член
Parcelable state;
Теперь,
@Override
protected void onPause() {
super.onPause();
state = recyclerView.getLayoutManager().onSaveInstanceState();
}
@Override
protected void onResume() {
super.onResume();
recyclerView.getLayoutManager().onRestoreInstanceState(state);
}
переопределите методы паузы и возобновления с помощью приведенного выше кода, и все готово!
Вы можете использовать
adapter.stateRestorationPolicy = StateRestorationPolicy.PREVENT_WHEN_EMPTY
который вводится в
recyclerview:1.2.0-alpha02
https://medium.com/androiddevelopers/restore-recyclerview-scroll-position-a8fbdc9a9334
но у него есть некоторые проблемы, такие как не работа с внутренним RecyclerView, и некоторые другие проблемы, которые вы можете проверить в разделе комментариев среднего сообщения.
Или вы можете использовать
ViewModel
с участием
SavedStateHandle
который работает для внутренних RecyclerViews, поворота экрана и смерти процесса.
Создать
ViewModel
с участием
saveStateHandle
val scrollState=
savedStateHandle.getLiveData<Parcelable?>(KEY_LAYOUT_MANAGER_STATE)
использовать Parcelable
scrollState
для сохранения и восстановления состояния, как указано в других сообщениях, или путем добавления прослушивателя прокрутки в RecyclerView и
recyclerView.addOnScrollListener(объект: RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
// save here
}
}
Когда вы используете recyclerView.getLayoutManager().onSaveInstanceState()
не забудьте проверить на нулевое значение:
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
if (recyclerView != null) {
outState.putParcelable(SCROLL_POSITION, recyclerView.getLayoutManager().onSaveInstanceState());
}
}
public class MainActivity extends AppCompatActivity {
Parcelable recyclerViewState;
.......
@Override
protected void onPause() {
super.onPause();
recyclerViewState = MainAnecdotesView.getLayoutManager().onSaveInstanceState();//save
}
@Override
protected void onResume()
{
super.onResume();
if(recyclerViewState!=null)
MainAnecdotesView.getLayoutManager().onRestoreInstanceState(recyclerViewState);//restore
}
}
Учитывая, что вы определили RecyclerView (mRecyclerView
) и LayoutManager (mLayoutManager
) в вашем коде и пока все работает нормально, решение по сохранению позиции (mPosition
) вашего RecyclerView выглядит так:
Используемые переменные и константы:
private final String RECYCLER_POSITION_KEY = "recycler_position"; private int mPosition = RecyclerView.NO_POSITION; private RecyclerView mRecyclerView; private LinearLayoutManager mLayoutManager; private static Bundle mBundleState;
В
onPause
метод:@Override protected void onPause() { super.onPause(); // Save RecyclerView state mBundleState = new Bundle(); mPosition = mLayoutManager.findFirstCompletelyVisibleItemPosition(); mBundleState.putInt(RECYCLER_POSITION_KEY, mPosition); }
В
onResume
метод:@Override protected void onResume() { super.onResume(); // Restore RecyclerView state if (mBundleState != null) { mPosition = mBundleState.getInt(RECYCLER_POSITION_KEY); if (mPosition == RecyclerView.NO_POSITION) mPosition = 0; // Scroll the RecyclerView to mPosition mRecyclerView.smoothScrollToPosition(mPosition); } }
В
onSaveInstanceState
метод:@Override public void onSaveInstanceState(Bundle outState) { // Save RecyclerView state outState.putInt(RECYCLER_POSITION_KEY, mLayoutManager.findFirstCompletelyVisibleItemPosition()); super.onSaveInstanceState(outState); }
В
onRestoreInstanceState
метод:@Override protected void onRestoreInstanceState(Bundle savedInstanceState) { // Restore RecyclerView state if (savedInstanceState.containsKey(RECYCLER_POSITION_KEY)) { mPosition = savedInstanceState.getInt(RECYCLER_POSITION_KEY); if (mPosition == RecyclerView.NO_POSITION) mPosition = 0; // Scroll the RecyclerView to mPosition mRecyclerView.smoothScrollToPosition(mPosition); } super.onRestoreInstanceState(savedInstanceState); }