Android答题应用RadioButton状态残留问题求助(附完整代码)
问题分析与解决方案
核心问题原因
- 流程顺序错位:点击"下一题"时先加载新题目,再验证上一题答案,导致
verifyAnswer拿新题的选项文本匹配新题答案,完全混淆了当前题与下一题的逻辑。 - LiveData重复注册:每次调用
loadQuestions都新增Observer,数据更新时多次触发,引发UI和判分混乱。 - 随机题目逻辑无效:每次
loadData重建1-15的列表并打乱,无法保证题目不重复。 - 题目序号初始化错误:
questionNumber未正确赋值,导致第一题显示序号异常。
具体修复步骤
1. 调整变量与初始化逻辑
将随机题目列表改为成员变量,仅初始化一次,确保题目不重复;修正第一题序号:
// 新增成员变量存储题目索引 private List<Integer> questionIndices; @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); // ... 其他控件初始化代码 // 初始化不重复的随机题目索引列表 questionIndices = new ArrayList<>(); for (int i = 0; i < 15; i++) { // 注意:List索引从0开始,原代码用1会导致越界 questionIndices.add(i); } Collections.shuffle(questionIndices); questionNumber = 1; // 初始化第一题序号 loadData(view); timeCount(); buttonNext.setOnClickListener(v -> { // 先验证当前题答案,再加载下一题 verifyCurrentAnswer(); loadData(view); }); }
2. 分离验证与加载逻辑
新增verifyCurrentAnswer方法,专门处理当前题的答案判断,避免与新题数据混淆:
private void verifyCurrentAnswer() { if (rg.getCheckedRadioButtonId() == -1) { // 用户未选选项,可添加提示逻辑或直接跳过 return; } RadioButton selectedRb = requireView().findViewById(rg.getCheckedRadioButtonId()); String selectedText = selectedRb.getText().toString(); // 用当前题的正确答案判分 if (selectedText.equalsIgnoreCase(rightAnswer)) { correctAnswer += 2; } rg.clearCheck(); // 清空选中状态,为下一题准备 }
3. 修复LiveData观察逻辑
将LiveData的Observer移到onViewCreated中仅注册一次,避免重复触发:
@Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); // ... 其他初始化代码 // 仅注册一次LiveData观察 viewModel.getMutableLiveData().observe(getViewLifecycleOwner(), questionModels -> { // 数据更新时刷新当前题UI if (count <= 10 && generatedIndex < questionModels.size()) { loadQuestions(view, generatedIndex); } }); }
4. 修正loadData的题目获取逻辑
从预打乱的列表中取未使用的题目索引,保证不重复:
private void loadData(View view) { if (count == 11) { buttonNext.setText("Submit"); } else if (count > 10) { submitTest(); return; } // 无剩余题目时直接提交 if (questionIndices.isEmpty()) { submitTest(); return; } generatedIndex = questionIndices.remove(0); loadQuestions(view, generatedIndex); count += 1; questionNumber = count; }
5. 移除错误的验证调用
删除loadQuestions中onChanged方法内的verifyAnswer(view)调用,避免加载新题时误判。
修改后的完整代码
public class QuizFragment extends Fragment { Button buttonNext; TextView tv, timing; RadioButton rb1, rb2, rb3, rb4; RadioGroup rg; int questionNumber, count = 1; int correctAnswer = 0; String rightAnswer = null; private QuestionViewModel viewModel; NavController navController; private String quizId, regNumber; private int generatedIndex; private AuthenticationViewModel authenticationViewModel; private List<Integer> questionIndices; // 存储题目索引,保证不重复 public QuizFragment() { // Required empty public constructor } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getActivity().getWindow().setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); viewModel = new ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory.getInstance( getActivity().getApplication() )).get(QuestionViewModel.class); authenticationViewModel = new ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory.getInstance( getActivity().getApplication() )).get(AuthenticationViewModel.class); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_quiz, container, false); } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); buttonNext = view.findViewById(R.id.button_next); regNumber = QuizFragmentArgs.fromBundle(getArguments()).getRegNumber(); tv = view.findViewById(R.id.textview_question); timing = view.findViewById(R.id.textview_time); rb1 = view.findViewById(R.id.radioButton); rb2 = view.findViewById(R.id.radioButton2); rb3 = view.findViewById(R.id.radioButton3); rb4 = view.findViewById(R.id.radioButton4); rg = view.findViewById(R.id.radioGroup); navController = Navigation.findNavController(view); quizId = QuizFragmentArgs.fromBundle(getArguments()).getQuizId(); viewModel.setQuizId(quizId); // 初始化不重复的随机题目索引 questionIndices = new ArrayList<>(); for (int i = 0; i < 15; i++) { questionIndices.add(i); } Collections.shuffle(questionIndices); questionNumber = 1; loadData(view); timeCount(); buttonNext.setOnClickListener(v -> { verifyCurrentAnswer(); loadData(view); }); // 仅注册一次LiveData观察 viewModel.getMutableLiveData().observe(getViewLifecycleOwner(), questionModels -> { if (count <= 10 && generatedIndex < questionModels.size()) { loadQuestions(view, generatedIndex); } }); } private void loadData(View view) { if (count == 11) { buttonNext.setText("Submit"); } else if (count > 10) { submitTest(); return; } if (questionIndices.isEmpty()) { submitTest(); return; } generatedIndex = questionIndices.remove(0); loadQuestions(view, generatedIndex); count += 1; questionNumber = count; } private void loadQuestions(View view, int index) { List<QuestionModel> questionModels = viewModel.getMutableLiveData().getValue(); if (questionModels == null || index >= questionModels.size()) { return; } QuestionModel currentQuestion = questionModels.get(index); rightAnswer = currentQuestion.getAnswer(); tv.setText(questionNumber + "." + currentQuestion.getQuestion()); rb1.setText(currentQuestion.getOption1()); rb2.setText(currentQuestion.getOption2()); rb3.setText(currentQuestion.getOption3()); rb4.setText(currentQuestion.getOption4()); } private void verifyCurrentAnswer() { if (rg.getCheckedRadioButtonId() == -1) { return; } RadioButton selectedRb = requireView().findViewById(rg.getCheckedRadioButtonId()); String selectedText = selectedRb.getText().toString(); if (selectedText.equalsIgnoreCase(rightAnswer)) { correctAnswer += 2; } rg.clearCheck(); } private void submitTest() { authenticationViewModel.updateStudentWithScore(regNumber, correctAnswer); authenticationViewModel.getMutableLiveData().observe(getViewLifecycleOwner(), firebaseDatabase -> { QuizFragmentDirections.ActionQuizFragmentToResultFragment action = QuizFragmentDirections.actionQuizFragmentToResultFragment(); action.setScore(correctAnswer); navController.navigate(action); }); } // 保留原有计时逻辑 private void timeCount() { // 原有实现代码 } }
内容的提问来源于stack exchange,提问作者Ukeme Elijah
相关产品推荐
相关产品推荐

