You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android答题应用RadioButton状态残留问题求助(附完整代码)

问题分析与解决方案

核心问题原因

  1. 流程顺序错位:点击"下一题"时先加载新题目,再验证上一题答案,导致verifyAnswer拿新题的选项文本匹配新题答案,完全混淆了当前题与下一题的逻辑。
  2. LiveData重复注册:每次调用loadQuestions都新增Observer,数据更新时多次触发,引发UI和判分混乱。
  3. 随机题目逻辑无效:每次loadData重建1-15的列表并打乱,无法保证题目不重复。
  4. 题目序号初始化错误: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 07:32:14