Android RecyclerView 保存状态信息

Android RecyclerView Saving State Information

我有一个 RecyclerView,其适配器包含我无法修改的对象的 SortedList。

我在 RecyclerView 中的卡片在展开时应该 expand/collapse 在点击时显示附加信息。问题是,自从 ViewHolder 被回收以来,似乎没有办法存储卡片是展开还是折叠的信息。

为了让事情变得更加困难,在我的适配器的开头和结尾添加了新项目,所以位置一直在变化。尽管新卡片应该显示为折叠状态,但当扩展卡片的 ViewHolder 为新卡片回收时,它们有时会显示为展开状态。这是我尝试直接在 ViewHolder 中保存 expand/collapse 信息的时候。

正确的解决方案似乎是使用具有两个属性的包装器对象:原始(不可修改的)对象和一个指示项目是展开还是折叠的布尔值。

然后在 RecyclerView 适配器的 onBindViewHolder() 方法中,您必须根据包装对象的状态将视图设置为展开或折叠。

@Override
public void onBindViewHolder(final ViewHolder ui, int position) {
    if(wrapper_objects.get(position).expanded) {
        expandView(ui);
    } else {
        collapseView(ui);
    }

    // expand/collapse on click
    ui.expand.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if(wrapper_objects.get(position).expanded) {
                collapseView(ui);
                wrapper_objects.get(position).expanded = false;
            } else {
                expandView(ui);
                wrapper_objects.get(position).expanded = true;
            }
        }
    });
}

另一个但罕见的问题可能是 API 有时 returns 与 SortedList 中已有的相同对象。在这种情况下,它们会覆盖包装对象中的 expand/collapse 状态。我为此找到的一个骇人听闻的解决方案是这样做的:

private SortedList<WrapperObject> wrapper_objects = new SortedList<>(WrapperObject.class, new SortedList.Callback<WrapperObject>(){
    @Override
     public boolean areContentsTheSame(WrapperObject old, WrapperObject new) {
        // keep state in new wrapper object
        new.expanded = old.expanded;

        return old.object.equals(new.object);
    }
}