У меня есть активность с ViewPager и 3 фрагментами, называемыми A, B, C. A имеет recyclerView, заполненный cardView, и каждая карта реализует и OnClickListener, что приводит к новому действию D. Я хочу иметь возможность сохранять положение прокрутки recyclerView при переключении вкладок и при возврате из открытого действия D.
то, что я сделал до сих пор во фрагменте A (тот, который содержит RecyclerView, выглядит так:
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
recyclerView = (RecyclerView)inflater.inflate(R.layout.event_fragment_layout, container,false);
linearLayoutManager = new LinearLayoutManager((getActivity()));
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setHasFixedSize(true);
return recyclerView;
}
public void onStart(){
//This is where my adapter is created and attached to the recyclerView
recyclerView.setAdapter(myadapter)
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable(RECYCLER_STATE,linearLayoutManager.onSaveInstanceState());
String saved = linearLayoutManager.onSaveInstanceState().toString();
Toast.makeText(getContext(),"Saving Instance State",Toast.LENGTH_SHORT).show();
Log.d("SAVE_CHECK ", saved);
}
@Override
public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
if(savedInstanceState!=null) {
Parcelable savedRecyclerViewState = savedInstanceState.getParcelable(RECYCLER_STATE);
if(savedRecyclerViewState!=null) {
linearLayoutManager.onRestoreInstanceState(savedRecyclerViewState);
Toast.makeText(getContext(), "Restoring Instance State", Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(getContext(), "SAVED STATE IS NULL", Toast.LENGTH_SHORT).show();
}
}
super.onViewStateRestored(savedInstanceState);
}
Я показываю оба Toast, поэтому блок выполняется (и это означает, что saveRecyclerViewState не равен нулю), но recyclerView всегда начинается с первой карты, несмотря ни на что. Также, когда я открываю новое действие, щелкнув карту, а затем возвращаюсь к фрагменту A, я получаю уведомление Toast о том, что состояние сохраняется, но не то, что в onViewRestored. Насколько я понимаю, в основном происходит то, что состояние моего linearLayoutManager сохраняется, но затем мне почему-то не удается передать информацию для восстановления позиции прокрутки. Что я делаю не так ?
РЕШЕНО: решил это сам, но это может помочь кому-то в будущем. TL; DR -> просто объявите адаптер в onCreateView, а затем вызовите yourRecyclerView.setAdapter(yourAdapter) как в OnCreateView, так и в OnResume(), остальная часть кода остается прежней
Что случилось потом ? Достаточно просто, я правильно сохранял состояние linearLayoutManager в onSavedInstanceState(), а затем правильно восстанавливал его в OnCreate, но я не смог заметить никакой разницы, поскольку сохраненное состояние состояния «перезаписывалось», устанавливая мой адаптер в OnStart. По шагам:
1) действие фрагмента вызывает onSavedInstanceState и сохраняет LinearLayoutManager моего RecyclerView в Parcelable.
2) приложение возвращается к фрагменту и вызывает onViewStateRestored()/OnCreateView(), там мы читаем из пакета и восстановите наш recyclerViewState
3)Теперь проблема вызывается OnStart(), и, конечно же, именно здесь объявляется мой адаптер, а затем устанавливается в recyclerView. Теперь старый recyclerView (с сохраненным состоянием) удален и заменен новым новым recyclerView без записи предыдущего.
Таким образом, просто установив адаптер в методе OnResume(), вы решу проблему. Я думаю, вы также можете решить эту проблему, оставив код в OnStart(), сохранив состояние старого recyclerView и затем передав его новому recyclerView в конце OnStart(). но это не очень чистое решение