保存 RecyclerView 状态的最佳方法是啥?
Posted
技术标签:
【中文标题】保存 RecyclerView 状态的最佳方法是啥?【英文标题】:What is the best way to save state of RecyclerView?保存 RecyclerView 状态的最佳方法是什么? 【发布时间】:2015-07-02 14:52:14 【问题描述】:我的片段在主要活动中包含 recyclerview
片段.java
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
super.onCreate(savedInstanceState);
View view = inflater.inflate(R.layout.activity_main, container, false);
initInstances(view);
setRetainInstance(true);
return view;
private void initInstances(View view)
mRecyclerView = (RecyclerView) view.findViewById(R.id.dialogList);
mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(mLayoutManager);
adapter = new MyAdapter(items);
mRecyclerView.setAdapter(mAdapter);
MainActivity.java
在 onCreate 方法中:
myFragment = (MyFragment) getSupportFragmentManager().findFragmentByTag(MyFragment.TAG);
if (MyFragment == null)
MyFragment = new MyFragment();
getSupportFragmentManager().beginTransaction().add(R.id.content_frame,
myFragment, MyFragment.TAG).commit();
但是当方向改变时,我的 RecyclerView 会重新绘制。
我尝试过像 How to prevent custom views from losing state across screen orientation changes 或 Saving and restoring view state android 这样覆盖 onSaveInstanceState
和 onRestoreInstanceState
来保存状态,但对我来说无济于事
当方向改变时如何正确保存 RecyclerView 和适配器项目的状态?
解决方案: 我的片段通过一些方法从 BaseFragment 扩展而来:
public class BaseFragment extends Fragment
Bundle savedState;
public BaseFragment()
super();
if (getArguments() == null)
setArguments(new Bundle());
@Override
public void onActivityCreated(Bundle savedInstanceState)
super.onActivityCreated(savedInstanceState);
if (!restoreStateFromArguments())
onFirstTimeLaunched();
protected void onFirstTimeLaunched()
@Override
public void onSaveInstanceState(Bundle outState)
super.onSaveInstanceState(outState);
saveStateToArguments();
public void saveStateToArguments()
if (getView() != null)
savedState = saveState();
if (savedState != null)
Bundle b = getArguments();
b.putBundle("internalSavedViewState8954201239547", savedState);
private boolean restoreStateFromArguments()
Bundle b = getArguments();
savedState = b.getBundle("internalSavedViewState8954201239547");
if (savedState != null)
onRestoreState(savedState);
return true;
return false;
private Bundle saveState()
Bundle state = new Bundle();
onSaveState(state);
return state;
protected void onRestoreState(Bundle savedInstanceState)
protected void onSaveState(Bundle outState)
@Override
public void onStart()
super.onStart();
@Override
public void onStop()
super.onStop();
@Override
public void onDestroyView()
super.onDestroyView();
saveStateToArguments();
在我的片段中,我重写方法并保存 mLayoutManager 的状态
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setRetainInstance(true);
@Override
protected void onSaveState(Bundle outState)
super.onSaveState(outState);
outState.putParcelable("myState", mLayoutManager.onSaveInstanceState());
@Override
protected void onRestoreState(Bundle savedInstanceState)
super.onRestoreState(savedInstanceState);
mLayoutManager.onRestoreInstanceState(savedInstanceState.getParcelable("myState"));
【问题讨论】:
配置更改和片段回栈之间缺乏一致性绝对是一场噩梦。谢谢你的主意。这似乎已经解决了我现在的问题。 【参考方案1】:我搜索了如何获取 RecyclerView 的滚动位置,但没有看到我可以在哪里检索它,所以我认为最好的解决方案是直接在您的 java 代码中处理旋转更改,并防止您的活动重新启动方向改变。
为防止在方向更改时重新启动,您可以关注this solution。
在阻止 Activity 重启后,您可以构建 2 个 xml 布局文件,一个用于纵向模式,一个用于横向模式,您在两个 xml 文件中添加一个 FrameLayout,为您的 RecyclerView 保留位置。
当 onConfigurationChange(Configuration newConfig) 方法被调用时,你调用 setContentView(int layoutFile) 并按照新的方向使用适当的 LayoutFile,并将你持有的 RecyclerView 添加到 FrameLayout 中你的类的成员中。
【讨论】:
以上是关于保存 RecyclerView 状态的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章
使用多个 RecyclerView 和其他视图保存/恢复 NestedScrollView 的状态