【问题标题】: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 changesSaving and restoring view state android 这样覆盖 onSaveInstanceStateonRestoreInstanceState 来保存状态,但对我来说无济于事

当方向改变时如何正确保存 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"));
}

【问题讨论】:

  • 配置更改和片段回栈之间缺乏一致性绝对是一场噩梦。谢谢你的主意。这似乎已经解决了我现在的问题。

标签: android android-fragments android-recyclerview


【解决方案1】:

我搜索了如何获取 RecyclerView 的滚动位置,但没有看到我可以在哪里检索它,所以我认为最好的解决方案是直接在您的 java 代码中处理旋转更改,并防止您的活动重新启动方向改变。

为防止在方向更改时重新启动,您可以关注this solution

在阻止 Activity 重启后,您可以构建 2 个 xml 布局文件,一个用于纵向模式,一个用于横向模式,您在两个 xml 文件中添加一个 FrameLayout,为您的 RecyclerView 保留位置。

当 onConfigurationChange(Configuration newConfig) 方法被调用时,你调用 setContentView(int layoutFile) 并按照新的方向使用适当的 LayoutFile,并将你持有的 RecyclerView 添加到 FrameLayout 中你的类的成员中。

【讨论】:

    猜你喜欢
    • 2018-08-14
    • 2015-04-28
    • 2010-12-05
    • 2012-01-08
    • 1970-01-01
    相关资源
    最近更新 更多