【问题标题】:Saving state custom RecyclerView保存状态自定义 RecyclerView
【发布时间】:2016-09-20 08:43:08
【问题描述】:

我创建了一个自定义RecyclerView,以便在我的应用程序列表中启用分页。我在恢复状态时遇到了崩溃。也许这个崩溃与支持库中的一个已知错误有关,但理论上,它已在支持库版本24.0.0:https://code.google.com/p/android/issues/detail?id=196430 中得到解决,但它仍然崩溃。

也许我做错了什么?我有一个 BadParcelableException ClassNotFoundException when unmarshalling: android.support.v7.widget.RecyclerView$SavedStateHere 试图重新创建 SavedState。

这是我在CustomRecyclerView 控制器中的SavedState 类:

public static class SavedState extends RecyclerView.BaseSavedState {

    public boolean isLastPage;
    public boolean isLoading;
    public int maxPages;
    public int pageSize;
    public int currentPage;
    public int firstVisibleItem;
    public Parcelable layoutManagerState;

    public SavedState(Parcelable superState) {
        super(superState);
    }

    public SavedState(Parcel source) {
        super(source);
        this.isLastPage = source.readByte() == 1;
        this.isLoading = source.readByte() == 1;
        this.maxPages = source.readInt();
        this.pageSize = source.readInt();
        this.currentPage = source.readInt();
        this.firstVisibleItem = source.readInt();
        this.layoutManagerState = source.readParcelable(LinearLayoutManager.SavedState.class.getClassLoader());
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        super.writeToParcel(dest, flags);
        dest.writeByte((byte) (isLastPage ? 1 : 0));
        dest.writeByte((byte) (isLoading ? 1 : 0));
        dest.writeInt(maxPages);
        dest.writeInt(pageSize);
        dest.writeInt(currentPage);
        dest.writeInt(firstVisibleItem);
        dest.writeParcelable(layoutManagerState, flags);
    }

    public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
        @Override
        public SavedState createFromParcel(Parcel source) {
            return new SavedState(source);
        }

        @Override
        public SavedState[] newArray(int size) {
            return new SavedState[size];
        }
    };
}

这里是我在控制器中保存和恢复状态的地方:

public Parcelable saveState(Parcelable superState) {
    SavedState savedState       = new SavedState(superState);
    savedState.isLastPage       = this.isLastPage;
    savedState.isLoading        = this.isLoading;
    savedState.maxPages         = this.maxPages;
    savedState.pageSize         = this.pageSize;
    savedState.currentPage      = this.currentPage;
    savedState.firstVisibleItem = this.firstVisibleItemPosition;

    if (layoutManager != null) {
        savedState.layoutManagerState = layoutManager.onSaveInstanceState();
    }

    return savedState;
}

public Parcelable restoreState(SavedState savedState) {

    this.isLastPage                 = savedState.isLastPage;
    this.isLoading                  = savedState.isLoading;
    this.maxPages                   = savedState.maxPages;
    this.pageSize                   = savedState.pageSize;
    this.currentPage                = savedState.currentPage;
    this.firstVisibleItemPosition   = savedState.firstVisibleItem;

    return savedState.layoutManagerState;
}

这是自定义 RecyclerView 中的 onSaveInstanceStateonRestoreInstanceState 实现:

    @Override
    protected Parcelable onSaveInstanceState() {

        return controller.saveState(super.onSaveInstanceState());
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {

        if (state instanceof EndlessRecyclerViewController.SavedState) {

            EndlessRecyclerViewController.SavedState savedState = (EndlessRecyclerViewController.SavedState) state;

            Parcelable layoutManagerState = controller.restoreState(savedState);

            getLayoutManager().onRestoreInstanceState(layoutManagerState);
            super.onRestoreInstanceState(savedState.getSuperState());
        }
        else
            super.onRestoreInstanceState(state);
    }

我还尝试从支持AbsSavedState 扩展SavedState,但仍然崩溃。而且我不确定是否必须致电LinearLayoutManageronSaveInstanceState...

谢谢!

【问题讨论】:

  • 不是扩展 BaseSaveState,而是简单地覆盖 recyclerview 中的 onsaveInstanceState 并将您需要的值保存在 bundle 中并覆盖 onrestoreinstancestate 并恢复这些值
  • 但是在 CustomViews 中,您没有在 onSaveInstanceState 中收到 Bundle,您必须使用您的数据创建一个自定义状态类并将其作为 Parcelable 在 onSaveInstanceState 中返回,对吗?

标签: android android-recyclerview savestate


【解决方案1】:

最后,我使用支持库版本 24.2.1 中的 AbsSavedState(因此,我从它扩展了 SavedState 类)解决了问题。并更改从以下位置接收Parcel 对象的constructor

public SavedState(Parcel source) {
  super(source);
  //... 
}

到:

public SavedState(Parcel source) {
  super(source, LinearLayoutManager.class.getClassLoader());
  //... 
}

【讨论】:

    【解决方案2】:

    当我第一次尝试your solution 时,我很高兴,因为它确实有效。然而,当我查看其他Android code 时,我发现有更好的解决方案。您需要添加一个新的构造函数并从创建者那里调用它。

    // add new constructor
    @RequiresApi(Build.VERSION_CODES.N)
    public SavedState(Parcel source, ClassLoader loader) {
        super(source, loader);
        this.isLastPage = source.readByte() == 1;
        this.isLoading = source.readByte() == 1;
        this.maxPages = source.readInt();
        this.pageSize = source.readInt();
        this.currentPage = source.readInt();
        this.firstVisibleItem = source.readInt();
        this.layoutManagerState = source.readParcelable(LinearLayoutManager.SavedState.class.getClassLoader());
    }
    
    public static final Creator<SavedState> CREATOR = new ClassLoaderCreator<SavedState>() {
    
        // add createFromParcel method with ClassLoader
        @Override
        public SavedState createFromParcel(Parcel source, ClassLoader loader)
        {
            return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ? new SavedState(source, loader) : new SavedState(source);
        }
    
        @Override
        public SavedState createFromParcel(Parcel source)
        {
            // call other createFromParcel method.    
            return createFromParcel(source, null);
        }
    
        @Override
        public SavedState[] newArray(int size) {
            return new SavedState[size];
        }
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多