Android使用ViewModel绑定RadioGroup旋转后选中丢失且报空指针异常
问题修复方案
1. 空指针异常问题
错误原因
你在ViewModel中直接持有了RadioGroup的实例,ViewModel的生命周期远长于Fragment/Activity,屏幕旋转触发页面重建时,旧的RadioGroup实例被销毁回收,ViewModel中持有的引用变为空,调用radioGroup.isSelected()时就会触发空指针。同时ViewModel持有View引用还会造成严重的内存泄漏。
修复规则
绝对不要在ViewModel中持有任何View、Context、Activity、Fragment的实例。
2. 屏幕旋转后选中状态丢失问题
错误原因
- 你用Boolean类型存储RadioGroup的选中状态,本身逻辑错误:RadioGroup的选中状态对应的是子RadioButton的唯一id,不是简单的是否选中布尔值
- Observer写在了
setOnCheckedChangeListener内部,每次用户点击RadioButton都会重复注册Observer,导致回调异常 - 调用
radioGroup.setSelected(check)设置选中是API用错:该方法是View通用的选中状态标识,不是RadioGroup用来选中指定子项的API,RadioGroup选中指定项需要调用check(对应RadioButton的id)
修复后完整代码
PagesVM.java
public class PagesVM extends ViewModel { // 存储选中的RadioButton ID,默认-1表示未选中 private MutableLiveData<Integer> selectedRadioId = new MutableLiveData<>(-1); public LiveData<Integer> getSelectedRadioId() { return selectedRadioId; } public void setSelectedRadioId(int checkedId) { selectedRadioId.setValue(checkedId); } }
FirstPage.java 核心逻辑
// 初始化ViewModel viewModel = new ViewModelProvider(requireActivity()).get(PagesVM.class); // 定义RadioGroup选中监听器 RadioGroup.OnCheckedChangeListener checkedChangeListener = (group, checkedId) -> { invisibleBtn.setVisibility(View.INVISIBLE); // 同步选中状态到ViewModel viewModel.setSelectedRadioId(checkedId); // 此处case替换为你布局中RadioButton对应的实际id,不要用硬编码的0/1/2/3/4 switch (checkedId) { case R.id.rb_option1: case R.id.rb_option2: case R.id.rb_option3: case R.id.rb_option4: count += 0; break; case R.id.rb_option5: count += 1; break; } }; // 注册Observer监听选中状态变化,注意要放在监听器外部,避免重复注册 viewModel.getSelectedRadioId().observe(getViewLifecycleOwner(), checkedId -> { if (checkedId != -1) { // 先临时移除监听器,避免设置选中时触发回调形成死循环 radioGroup.setOnCheckedChangeListener(null); radioGroup.check(checkedId); radioGroup.setOnCheckedChangeListener(checkedChangeListener); } }); // 给RadioGroup绑定监听器 radioGroup.setOnCheckedChangeListener(checkedChangeListener);
额外注意
删除原来FirstPage中onDestroy方法里调用slectItem()的逻辑,以及PagesVM中所有和RadioGroup引用相关的代码。
内容的提问来源于stack exchange,提问作者Nurtoza Ayxo'jayev
相关产品推荐
相关产品推荐

