代码之家  ›  专栏  ›  技术社区  ›  Hector

如何在设备旋转时恢复Android RecyclerView列表项中的复选框状态

  •  0
  • Hector  · 技术社区  · 6 年前

    我当前的Android应用程序包含一个RecyclerView,列表中的每个项目都有一个复选框。

    我的问题是,在屏幕旋转时,复选框总是返回到未选中状态。

    从调试日志中,我可以看到列表状态正确地保存了每个列表项的选中/未选中状态。

    我还注销了适配器构造函数中的列表,该列表还显示选中状态仍然有效。

    然而当 onBindViewHolder 如果列表项都未选中,则称为。

    以下是我的代码片段:-

      @Override
        protected void onCreate(final Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.my_layout);
    
            manageViewModel();
            recyclerView = findViewById(R.id.my_rv);
    
            final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
            recyclerView.setLayoutManager(layoutManager);
            recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
            adapter = new MedicationAdapter(viewModel.getList(), this);
            recyclerView.setAdapter(adapter);
    
       }
    
    
    
    protected void onSaveInstanceState(Bundle state) {
        super.onSaveInstanceState(state);
        viewModel.saveList(adapter.getList());
    }
    
    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
    }
    

    “我的列表项”复选框在xml中定义如下:-

    <android.support.v7.widget.AppCompatCheckBox
                android:id="@+id/my_checkbox_header"
                android:layout_width="wrap_content"
                android:saveEnabled="false"
                android:layout_height="wrap_content"
                android:layout_gravity="top"
                android:text="" />
    

    在设备旋转时,将复选框状态保留在RecyclerView项中的正确方法是什么?

    我的适配器代码:-

        public class MusicalAdapter extends RecyclerView.Adapter<MusicalAdapter.ViewHolder> {
    
            private static final String TAG = "MusicalAdapter";
            private int previousExpandedPosition = -1;
            private int mExpandedPosition = -1;
    
            private final List<MusicalUI> musicals = new ArrayList<>();
            private final ItemClickListener clickListener;
    
            MusicalAdapter(final List<MusicalUI> musicals, final ItemClickListener clickListener) {
                this.musicals.clear();
                this.musicals.addAll(musicals);
    //AT THIS POINT THE CHECKED VALUES ARE AS EXPECTED
    
                this.clickListener = clickListener;
            }
    
            @NonNull
            @Override
            public MusicalAdapter.ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
                final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.all_disco_item_x, parent, false);
                return new ViewHolder(view);
            }
    
            @Override
            public void onBindViewHolder(@NonNull final MusicalAdapter.ViewHolder holder, final int position) {
                final MusicalUI musical = musicals.get(position);
    
                Log.d(TAG, "onBindViewHolder() called with: musical = [" + musical.getChecked());
    
    // AT THI SPOINT THE CHECKED VALUES ARE ALWAYS FALSE!!!!!!!!
                final boolean isExpanded = position == mExpandedPosition;
    
    
                for (final MusicalUI musicalx : musicals) {
                    Log.d(TAG, "onBindViewHolder(): " + musicalx.getChecked());
                }
    
                // Header
                holder.discoDetailsHeaderLayout.setVisibility(View.VISIBLE);
                holder.musicalNameHeader.setText(musical.getDiscoName());
    
                holder.discoSelectedHeader.setOnCheckedChangeListener(null);
                holder.discoSelectedHeader.setChecked(musical.getChecked());
                holder.discoSelectedHeader.setOnCheckedChangeListener((buttonView, isChecked) -> musical.setChecked(isChecked));
    
    
                if (isExpanded)
                    previousExpandedPosition = position;
    
                holder.itemView.setOnClickListener(v -> {
                    mExpandedPosition = isExpanded ? -1 : position;
                    notifyItemChanged(previousExpandedPosition);
                    notifyItemChanged(position);
                });
    
            }
    
            @Override
            public int getItemCount() {
                return musicals.size();
            }
    
    
            MusicalUI getItem(final int position) {
                return musicals.get(position);
            }
    
            void updateList(final List<MusicalUI> newMusicals) {
                final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new GenericDiffUtilCallback<>(this.musicals, newMusicals));
                diffResult.dispatchUpdatesTo(this);
    
                this.musicals.clear();
                this.musicals.addAll(newMusicals);
            }
    
            List<MusicalUI> getList() {
                return musicals;
            }
    
            /**
             *
             */
            public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, CompoundButton.OnCheckedChangeListener {
        ...
                }
    
    
            }
        }
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   rgaraisayev    6 年前

    它会发生变化,因为当旋转发生变化时,您的活动会重新启动。您可以编写大量代码来恢复您的状态 您可以避免重新启动。这是正确的方法

    使您的活动不会在旋转更改中重新启动

    在AndroidManifest中找到您的活动并添加

    android:configChanges="orientation"

    Android还建议在大多数情况下避免使用它

    注意:自行处理配置更改可能会使更改更加复杂 更难使用替代资源,因为系统确实如此 当您必须避免由于故障而重新启动时,被认为是最后的选择

    要声明您的活动处理配置更改,请编辑 在清单文件中包含 android:configChanges属性的文档。最 常用值为“方向”、“屏幕大小”和 屏幕方向改变。

    More Info