Android Firebase问答应用:点击按钮后问题未刷新,updateQuestion方法异常
问题分析与解决方案:Android Firebase问答应用无法刷新问题内容
嘿,我一眼就瞅出问题根源了——你的mDatabaseReference从初始化开始就绑定死了第一个问题的节点,之后就算调用updateQuestion(),它也还是在监听旧节点,自然不会加载新内容!
核心问题拆解
你在onCreate里初始化mDatabaseReference时,用的是Question + mQuestionNumber(此时mQuestionNumber是1),之后每次调用updateQuestion(),这个引用都没有更新,始终指向第一个问题的数据库节点。所以不管题号怎么递增,展示的还是第一个问题的内容。
具体修改方案
我给你整理了优化后的代码,关键是把数据库引用的初始化移到updateQuestion()内部,同时封装重复的点击逻辑减少冗余:
// 先在类里声明成员变量,注意初始化题号和分数 private int mQuestionNumber = 1; private int mScore = 0; private DatabaseReference mDatabaseReference; private ValueEventListener mQuestionListener; // 保存监听器,方便后续移除避免内存泄漏 private String answer; // 把答案设为成员变量,方便点击事件里调用 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.taking_quiz); que = (TextView) findViewById(R.id.txtQuestion); opt1 = (Button) findViewById(R.id.button1); opt2 = (Button) findViewById(R.id.button2); opt3 = (Button) findViewById(R.id.button3); opt4 = (Button) findViewById(R.id.button4); qn = (TextView) findViewById(R.id.number); sco = (TextView) findViewById(R.id.score); qn.setText("Question : 1"); sco.setText("Score : 0"); RecieversId = getIntent().getStringExtra("Recievers_Id"); mAuth = FirebaseAuth.getInstance(); currentUser = mAuth.getCurrentUser(); // 统一设置选项点击事件,避免重复代码 setupOptionClickListener(opt1); setupOptionClickListener(opt2); setupOptionClickListener(opt3); setupOptionClickListener(opt4); // 加载第一个问题 updateQuestion(); } private void updateQuestion() { // 先移除旧的监听器,防止内存泄漏和重复监听 if (mDatabaseReference != null && mQuestionListener != null) { mDatabaseReference.removeEventListener(mQuestionListener); } // 根据最新的题号,获取对应数据库节点的引用 mDatabaseReference = FirebaseDatabase.getInstance() .getReference() .child("Users") .child(RecieversId) .child("Quiz") .child("Question" + mQuestionNumber); mQuestionListener = new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { // 判断当前题号对应的节点是否存在,不存在就跳转到结束页面 if (!dataSnapshot.exists()) { Intent intent = new Intent(TakingQuiz.this, TakingQuizDone.class); intent.putExtra("Score", mScore); startActivity(intent); finish(); return; } // 更新页面内容 String question = dataSnapshot.child("Question").getValue().toString(); answer = dataSnapshot.child("Answer").getValue().toString(); String option1 = dataSnapshot.child("Option1").getValue().toString(); String option2 = dataSnapshot.child("Option2").getValue().toString(); String option3 = dataSnapshot.child("Option3").getValue().toString(); String option4 = dataSnapshot.child("Option4").getValue().toString(); que.setText(question); opt1.setText(option1); opt2.setText(option2); opt3.setText(option3); opt4.setText(option4); } @Override public void onCancelled(DatabaseError databaseError) { Toast.makeText(TakingQuiz.this, "加载问题失败,请检查网络", Toast.LENGTH_SHORT).show(); } }; mDatabaseReference.addValueEventListener(mQuestionListener); } // 封装通用的选项点击逻辑,减少重复代码 private void setupOptionClickListener(final Button optionBtn) { optionBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String selectedOption = optionBtn.getText().toString(); // 判断选项是否正确,更新分数和按钮颜色 if (selectedOption.equals(answer)) { optionBtn.setBackgroundColor(Color.GREEN); mScore++; sco.setText("Score : " + mScore); } else { optionBtn.setBackgroundColor(Color.RED); sco.setText("Score : " + mScore); } // 延迟1.5秒后加载下一题 new Handler().postDelayed(new Runnable() { @Override public void run() { mQuestionNumber++; qn.setText("Question : " + mQuestionNumber); updateQuestion(); optionBtn.setBackgroundColor(Color.CYAN); } }, 1500); } }); }
额外注意点
- 确保数据库里的节点命名和代码里的
Question + mQuestionNumber完全匹配(比如Question1、Question2) - 每次加载新问题前移除旧监听器,能避免不必要的资源消耗和内存泄漏
- 在
onDataChange里判断节点是否存在,能实现自动跳转到结束页面的逻辑
内容的提问来源于stack exchange,提问作者user9646251
相关产品推荐
相关产品推荐

