Sorry for the bad english.
I want an exact position. And after the activity / fragment has been destroyed (regardless of whether I destroy it or the system destroys it), I open the activity / fragment again, RecyclerView can also the same position, since it was destroyed.
“same” does not mean “position position”, because perhaps the item is only displayed for the last time.
I want to restore exactly the same position.
I tried several ways below, but no one is perfect.
Can anybody help?
1. The first way.
I use onScrolled to calculate the exact scroll position when stopping the scroll, save the position. When the spinner changes the dataset or onCreat fragment, restore the position of the selected dataset. Some datasets can have many rows.
It can save and restore after the application is destroyed, but can there be too many calculations?
It will cause
Skipped 60 frames! The application may be doing too much work on its main thread. attempt to finish an input event but the input event receiver has already been disposed. android total arena pages for jit.
And if scrollY is huge, for example 111111 , when you open the RecyclerView fragment, it will first display the list starting from the first element, and after some delay it will scroll to scrollY position.
How to do this without delay?
recyclerView.addOnScrollListener(new OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, final int dy) { super.onScrolled(recyclerView, dx, dy); handler.post(new Runnable() { @Override public void run() { if (isTableSwitched) { scrollY = 0; isTableSwitched = false; } scrollY = scrollY + dy; Log.i("dy——scrollY——table", String.valueOf(dy) + "——" + String.valueOf(scrollY) + tableName); } }); } @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); switch (newState) { case RecyclerView.SCROLL_STATE_IDLE: saveRecyclerPosition(tableName, scrollY); break; case RecyclerView.SCROLL_STATE_DRAGGING: break; case RecyclerView.SCROLL_STATE_SETTLING: break; } } }); public void saveRecyclerPosition(String tableName, int y) { prefEditorSettings.putInt(KEY_SCROLL_Y + tableName, y); prefEditorSettings.commit(); } public void restoreRecyclerViewState(final String tableName) { handler.post(new Runnable() { @Override public void run() { recyclerView.scrollBy(0, prefSettings.getInt(KEY_SCROLL_Y + tableName, 0)); } }); }
2. The second way.
This works fine, but it can only work in the fragment life cycle.
I am trying to use ObjectOutputStream and ObjectInputStream to save and restore a HashMap , but it does not work.
How to keep it in memory?
private HashMap <String, Parcelable> hmRecyclerViewState = new HashMap<String, Parcelable>(); public void saveRecyclerPosition(String tableName) { recyclerViewState = recyclerView.getLayoutManager().onSaveInstanceState(); hmRecyclerViewState.put(tableName, recyclerViewState); } public void restoreRecyclerViewState(final String tableName) { if ( hmRecyclerViewState.get(tableName) != null) { recyclerViewState = hmRecyclerViewState.get(tableName); recyclerView.getLayoutManager().onRestoreInstanceState(recyclerViewState); recyclerViewState = null; }
3. The third way.
I am changing the second method, use the Bundle instead of the HashMap , but it has the same issue, does not work when from the fragment life cycle.
I use to manually serialize / deserialize the android package to save the Bundle in memory, but when it is restored, it does not receive a valid Bundle .
==================================================== ======================= Solution
Thanks everyone!
Finally, I will solve this problem, you can see it in my code , just see these 2 methods: saveRecyclerViewPosition and restoreWordRecyclerViewPosition .