在android片段中维护设备旋转上的列表项位置

在android片段中维护设备旋转上的列表项位置,android,android-fragments,android-recyclerview,android-fragmentactivity,Android,Android Fragments,Android Recyclerview,Android Fragmentactivity,在一个片段中,我试图保存RecyclerView列表的滚动状态,但不知怎的,它没有保存状态。由于它是一个片段,我将重写onSaveInstanceState()和onActivityCreated()方法以保存滚动位置。甚至尝试在onViewStateRestored()方法中实现。我看到了一些关于保存滚动状态的相关帖子,但它不起作用。请让我知道我在哪里失败了。下面是我的代码: public class RecipeListFragment extends Fragment implem

在一个片段中,我试图保存RecyclerView列表的滚动状态,但不知怎的,它没有保存状态。由于它是一个片段,我将重写onSaveInstanceState()和onActivityCreated()方法以保存滚动位置。甚至尝试在onViewStateRestored()方法中实现。我看到了一些关于保存滚动状态的相关帖子,但它不起作用。请让我知道我在哪里失败了。下面是我的代码:

public class RecipeListFragment extends Fragment
    implements RecipeListContract.View {
@BindView(R.id.recipe_list_recycler_view)
RecyclerView mRecipeListRecyclerView;
@BindView(R.id.recipe_list_progress_bar)
ProgressBar mRecipeListProgressBar;

@BindInt(R.integer.grid_column_count)
int mGridColumnCount;
@BindString(R.string.recipe_list_sync_completed)
String mRecipeListSyncCompleted;
@BindString(R.string.recipe_list_connection_error)
String mRecipeListConnectionError;

GridLayoutManager gridLayoutManager;
Parcelable savedRecyclerLayoutState;

Unbinder unbinder;

private static final String SAVED_LAYOUT_MANAGER
        = "com.learnwithme.buildapps.bakingapp.ui.recipelist.fragment";

private RecipeListContract.Presenter mRecipeListPresenter;
private RecipeListAdapter mRecipeListAdapter;

public RecipeListFragment() { }

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup 
container, @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_recipe_list, container, 
false);
unbinder = ButterKnife.bind(this, view);

mRecipeListAdapter = new RecipeListAdapter(
            getContext(),
            new ArrayList<>(0),
            recipeId -> mRecipeListPresenter.loadRecipeDetails(recipeId)
);
mRecipeListAdapter.setHasStableIds(true);

    gridLayoutManager = new GridLayoutManager(getContext(), 
mGridColumnCount);
    mRecipeListRecyclerView.setLayoutManager(gridLayoutManager);
    mRecipeListRecyclerView.setHasFixedSize(true);
    mRecipeListRecyclerView.setAdapter(mRecipeListAdapter);

    return view;
}

@Override
public void onPause() {
    super.onPause();
    mRecipeListPresenter.unsubscribe();
}

@Override
public void onResume() {
    super.onResume();
    mRecipeListPresenter.subscribe();
}

@Override
public void onSaveInstanceState() { }

@Override
public void onSaveInstanceState(Bundle bundle) {
    super.onSaveInstanceState(bundle);
    if(bundle != null) {
        bundle.putParcelable(SAVED_LAYOUT_MANAGER,
                mRecipeListRecyclerView
                    .getLayoutManager()
                    .onSaveInstanceState());
        Timber.d("instance state=>", 
mRecipeListRecyclerView.getLayoutManager().onSaveInstanceState());
    }
}

@Override
public void onViewStateRestored(@Nullable Bundle bundle) {
    super.onViewStateRestored(bundle);
    if(bundle != null) {
        savedRecyclerLayoutState = 
bundle.getParcelable(SAVED_LAYOUT_MANAGER);
        Timber.d("onViewStateRestored savedRecyclerLayoutState=>", 
savedRecyclerLayoutState);
        mRecipeListRecyclerView
                .getLayoutManager()
                .onRestoreInstanceState(savedRecyclerLayoutState);
    }
}

@Override
public void onActivityCreated(@Nullable Bundle bundle) {
    super.onActivityCreated(bundle);
    if(bundle != null) {
        savedRecyclerLayoutState = 
bundle.getParcelable(SAVED_LAYOUT_MANAGER);
        Timber.d("onViewStateRestored savedRecyclerLayoutState=>",
                savedRecyclerLayoutState);
        mRecipeListRecyclerView
                .getLayoutManager()
                .onRestoreInstanceState(savedRecyclerLayoutState);
    }
}

@Override
public void onDestroyView() {
    super.onDestroyView();
    unbinder.unbind();
}

public static RecipeListFragment newInstance() {
    return new RecipeListFragment();
}

@Override
public void setPresenter(RecipeListContract.Presenter recipeListPresenter) {
    this.mRecipeListPresenter = recipeListPresenter;
}

@Override
public void showRecipeList(List<Recipe> recipeList) {
    mRecipeListAdapter.refreshRecipes(recipeList);
}

@Override
public void loadProgressBar(boolean show) {
    setViewVisibility(mRecipeListRecyclerView, !show);
    setViewVisibility(mRecipeListProgressBar, show);
}

@Override
public void displayCompletedMessage() {
    Toast.makeText(getContext(), mRecipeListSyncCompleted, 
Toast.LENGTH_SHORT).show();
}

@Override
public void displayErrorMessage() {
    Toast.makeText(getContext(), mRecipeListConnectionError, 
Toast.LENGTH_SHORT).show();
}

@Override
public void displayRecipeDetails(int recipeId) {
    startActivity(RecipeDetailsActivity.prepareIntent(getContext(), 
recipeId));
}

private void setViewVisibility(View view, boolean visible) {
    if (visible) {
        view.setVisibility(View.VISIBLE);
    } else {
        view.setVisibility(View.INVISIBLE);
    }
}
}
公共类RecipeListFragment扩展了片段
实现RecipeListContract.View{
@BindView(R.id.recipe\u list\u recycler\u视图)
RecyclerView mRecipeListRecyclerView;
@BindView(R.id.配方\列表\进度\栏)
ProgressBar mRecipeListProgressBar;
@BindInt(R.integer.grid\u column\u count)
int-mGridColumnCount;
@BindString(R.string.recipe\u list\u sync\u完成)
字符串mrecipelistsyncompled;
@BindString(R.string.recipe\u list\u connection\u error)
字符串mrecipleListConnectionError;
GridLayoutManager GridLayoutManager;
可包裹的储物柜在外;
无阻碍无阻碍;
私有静态最终字符串已保存\u布局\u管理器
=“com.learnwithme.buildapps.bakingapp.ui.recipelist.fragment”;
私人RecipeListContract.Presenter mRecipeListPresenter;
私人RecipeListAdapter mrecipleListAdapter;
公共RecipeListFragment(){}
@可空
@凌驾
创建视图上的公共视图(LAYOUTINGER充气机,@Nullable ViewGroup
容器,@Nullable Bundle savedInstanceState){
视图=充气机。充气(R.layout.fragment\u配方列表,容器,
假);
unbinder=ButterKnife.bind(这个,视图);
mRecipeListAdapter=新的RecipeListAdapter(
getContext(),
新ArrayList(0),
recipeId->mRecipeListPresenter.loadRecipeDetails(recipeId)
);
mRecipeListAdapter.setHasStableIds(true);
gridLayoutManager=新建gridLayoutManager(getContext(),
mGridColumnCount);
mrecipelistrecyclererview.setLayoutManager(gridLayoutManager);
mRecipeListRecyclerView.setHasFixedSize(true);
mRecipeListRecyclerView.setAdapter(mRecipeListAdapter);
返回视图;
}
@凌驾
公共无效暂停(){
super.onPause();
mRecipeListPresenter.unsubscribe();
}
@凌驾
恢复时公开作废(){
super.onResume();
mRecipeListPresenter.subscribe();
}
@凌驾
在SaveInstanceState(){}上公共无效
@凌驾
SaveInstanceState上的公共无效(捆绑){
super.onSaveInstanceState(bundle);
if(bundle!=null){
bundle.putParcelable(已保存的布局管理器),
mrecipelistrecyclererview
.getLayoutManager()
.onSaveInstanceState());
Timber.d(“实例状态=>”,
mRecipeListRecycleView.getLayoutManager().onSaveInstanceState());
}
}
@凌驾
public void onViewStateRestored(@Nullable Bundle){
super.onViewStateRestored(bundle);
if(bundle!=null){
savedRecyclerLayoutState=
bundle.getParcelable(已保存的布局管理器);
Timber.d(“onViewStateRestored savedRecyclerLayoutState=>”,
savedRecyclerLayoutState);
mrecipelistrecyclererview
.getLayoutManager()
.onRestoreInstanceState(savedRecyclerLayoutState);
}
}
@凌驾
已创建ActivityCreated(@Nullable Bundle)上的公共无效{
super.onActivityCreated(bundle);
if(bundle!=null){
savedRecyclerLayoutState=
bundle.getParcelable(已保存的布局管理器);
Timber.d(“onViewStateRestored savedRecyclerLayoutState=>”,
savedRecyclerLayoutState);
mrecipelistrecyclererview
.getLayoutManager()
.onRestoreInstanceState(savedRecyclerLayoutState);
}
}
@凌驾
公共无效onDestroyView(){
super.onDestroyView();
unbinder.unbind();
}
公共静态RecipeListFragment newInstance(){
返回新的RecipeListFragment();
}
@凌驾
public void setPresenter(RecipeListContract.Presenter recipeListPresenter){
this.mRecipeListPresenter=recipeListPresenter;
}
@凌驾
公共无效显示recipeList(列表recipeList){
mRecipeListAdapter.刷新食谱(recipeList);
}
@凌驾
公共void加载进度条(布尔显示){
setViewVisibility(mrecipleListRecyclerView,!show);
setViewVisibility(mRecipeListProgressBar,显示);
}
@凌驾
public void displayCompletedMessage(){
Toast.makeText(getContext(),mrecipleListSyncCompleted,
吐司。长度(短)。show();
}
@凌驾
public void displayErrorMessage(){
Toast.makeText(getContext(),mrecipleListConnectionError,
吐司。长度(短)。show();
}
@凌驾
公共void显示RecipeDetails(int recipeId){
startActivity(RecipedDetailsActivity.PrepareContent(getContext()),
recipeId);
}
私有void setViewVisibility(视图,布尔可见){
如果(可见){
view.setVisibility(view.VISIBLE);
}否则{
view.setVisibility(view.INVISIBLE);
}
}
}

我自己解决了这个问题。问题是在onSaveInstanceState()中保存设备的滚动位置,并在onViewRestored()方法中恢复相同的位置

另外,在loadProgress()方法中,我必须设置scrollToPosition(),并保存滚动位置

@Override
public void loadProgressBar(boolean show) {
    setViewVisibility(mRecipeListRecyclerView, !show);
    setViewVisibility(mRecipeListProgressBar, show);
    mRecipeListRecyclerView.scrollToPosition(mScrollPosition);
}
另外,还需要记住的是,无需在onResume()方法中恢复任何内容,因为演示者回调将被调用,并且视图将被重置

@Override
public void loadProgressBar(boolean show) {
    setViewVisibility(mRecipeListRecyclerView, !show);
    setViewVisibility(mRecipeListProgressBar, show);
    mRecipeListRecyclerView.scrollToPosition(mScrollPosition);
}