android - 如何在设备旋转上的 Android RecyclerView 列表项中恢复复选框状态
问题描述
我当前的 Android 应用程序包含一个 RecyclerView,它在列表中的每个项目中都有一个复选框。
我的问题是,在屏幕旋转时,复选框总是返回到未选中状态。
我将更新的列表项存储在我的活动 ViewModel 中,并将此保存的列表传递回 onCreate 中的适配器
从我的调试日志中,我可以看到列表状态正确地保存了每个列表项的选中/未选中状态。
我还注销了适配器构造函数中的列表,该列表也显示检查状态仍然有效。
但是,当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 {
...
}
}
}
解决方案
它会发生变化,因为当轮换发生变化时,您的活动会重新启动。您可以编写大量代码来恢复您的状态,也可以避免重新启动。这是正确的方法
使您的活动不会在轮换更改中重新启动
在 AndroidManifest 中找到您的活动并添加
android:configChanges="orientation"
Android 还建议在大多数情况下避免使用它
它说让android自己处理配置更改
注意:自己处理配置更改会使使用替代资源变得更加困难,因为系统不会自动为您应用它们。当您必须避免由于配置更改而重新启动并且不建议用于大多数应用程序时,应将此技术视为最后的手段。
要声明您的活动处理配置更改,请在清单文件中编辑适当的元素以包含 android:configChanges 属性,其值表示您要处理的配置。android:configChanges 属性的文档中列出了可能的值。最常用的值是“orientation”、“screenSize”和“keyboardHidden”。“orientation”值可防止屏幕方向更改时重新启动。
推荐阅读
- postgresql - 从laravel中的json字段`field_value`转换值的正确方法是什么?
- c# - C#:在 NJsonSchema 中将模式合并为一个不起作用
- excel - “@”符号出现在我的用户创建的 VBA 函数的前面 - 为什么?
- android - 无法在 Jetpack Compose 中设置排版
- lua - 相对于已执行的 Lua 文件,如何打开文本文件?
- kubernetes - Istio 标签不匹配
- javascript - 重新安装相同组件时如何防止相同的 img src 提取
- c# - 是否需要在后台服务中使用 ExecuteAsyn?
- c# - 如何在数据库中获取 1 个月的报告到列表框 c#
- python - 在 numpy 中复制火炬标准化