I'm building a quiz app using Android's ViewPager2 to display questions. Each time a user answers a question, the app updates their score. However, I've encountered an issue where even after answering all 6 questions correctly, the ResultFragment displays "Your Score: 5" instead of the expected "Your Score: 6". The score is stored in a HashSet, and I increment the score by adding the question index to this set. Everything works fine for the first 5 questions, but it seems like the problem is on the last question. Will appreciate any help thanks!
**QuizFragment.java: **
package com.example.project4;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.fragment.app.Fragment;
import androidx.viewpager2.widget.ViewPager2;
import java.util.List;
import java.util.HashSet;
import java.util.Set;
public class QuizFragment extends Fragment {
private List<Question> questionList;
ViewPager2 viewPager;
final Set<Integer> answeredCorrectly = new HashSet<>();
private ViewPager2.OnPageChangeCallback onPageChangeCallback;
private static final String ARG_QUIZ_ID = "quiz_id";
private long quizId;
public void markQuestionAsCorrect(int questionIndex) {
answeredCorrectly.add(questionIndex);
Log.d("QuizFragment", "Answered question [" + questionIndex + "] correctly.");
}
public void displayFinalScore() {
int userScore = answeredCorrectly.size();
Log.d("QuizFragment", "displayFinalScore: " + userScore);
viewPager.setCurrentItem(questionList.size());
QuizPagerAdapter adapter = (QuizPagerAdapter) viewPager.getAdapter();
if (adapter.resultFragment != null) {
Log.d("QuizFragment", "Calling updateScore after this. displayFinalScore: " + userScore);
adapter.resultFragment.updateScore(userScore);
}
}
public static QuizFragment newInstance(long quizId) {
QuizFragment fragment = new QuizFragment();
Bundle args = new Bundle();
args.putLong(ARG_QUIZ_ID, quizId);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
quizId = getArguments().getLong(ARG_QUIZ_ID);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_quiz, container, false);
DatabaseHelper dbHelper = new DatabaseHelper(getContext());
questionList = dbHelper.getQuestionsForQuiz(quizId);
viewPager = view.findViewById(R.id.viewPager);
QuizPagerAdapter pagerAdapter = new QuizPagerAdapter(this, questionList);
Log.d("QuizFragment", "QuestionsList: " + questionList.toString());
viewPager.setAdapter(pagerAdapter);
onPageChangeCallback = new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
super.onPageSelected(position);
if (position == questionList.size()) {
saveQuizResult();
}
}
};
viewPager.registerOnPageChangeCallback(onPageChangeCallback);
return view;
}
private void saveQuizResult() {
DatabaseHelper dbHelper = new DatabaseHelper(getContext());
int score = answeredCorrectly.size();
dbHelper.updateQuizResult(quizId, score);
}
@Override
public void onDestroyView() {
super.onDestroyView();
viewPager.unregisterOnPageChangeCallback(onPageChangeCallback);
}
}
**QuestionFragment.java: **
package com.example.project4;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import androidx.fragment.app.Fragment;
public class QuestionFragment extends Fragment {
private Question currentQuestion;
private RadioButton selectedAnswer;
private int questionIndex;
private int totalQuestions;
public static QuestionFragment newInstance(Question question, int index, int total) {
QuestionFragment fragment = new QuestionFragment();
fragment.currentQuestion = question;
fragment.questionIndex = index;
fragment.totalQuestions = total;
return fragment;
}
public boolean isAnswerCorrect() {
return selectedAnswer != null && currentQuestion.getCapitalCity().equals(selectedAnswer.getText().toString());
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_question, container, false);
TextView questionTextView = view.findViewById(R.id.questionText);
RadioButton optionA = view.findViewById(R.id.optionA);
RadioButton optionB = view.findViewById(R.id.optionB);
RadioButton optionC = view.findViewById(R.id.optionC);
RadioGroup radioGroup = view.findViewById(R.id.radioGroup);
questionTextView.setText("What is the capital city of " + currentQuestion.getState() + "?");
optionA.setText(currentQuestion.getCapitalCity());
optionB.setText(currentQuestion.getSecondCity());
optionC.setText(currentQuestion.getThirdCity());
radioGroup.setOnCheckedChangeListener((group, checkedId) -> {
selectedAnswer = view.findViewById(checkedId);
if (isAnswerCorrect() && getParentFragment() instanceof QuizFragment) {
((QuizFragment) getParentFragment()).markQuestionAsCorrect(questionIndex);
if (questionIndex == totalQuestions - 1) {
Log.d("QuestionFragment", "Caliing displayFinalScore()");
((QuizFragment) getParentFragment()).displayFinalScore();
((QuizFragment) getParentFragment()).viewPager.getAdapter().notifyDataSetChanged();
}
}
});
return view;
}
}
**QuizPagerAdapter.java: **
package com.example.project4;
import android.util.Log;
import androidx.fragment.app.Fragment;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import java.util.Arrays;
import java.util.List;
public class QuizPagerAdapter extends FragmentStateAdapter {
private final Fragment fragment;
private final List<Question> questionList;
ResultFragment resultFragment;
public QuizPagerAdapter(Fragment fragment, List<Question> questionList) {
super(fragment);
this.fragment = fragment;
this.questionList = questionList;
}
@Override
public Fragment createFragment(int position) {
Log.d("QuizPagerAdapter", "Position:" + position);
if (position == questionList.size()) {
Log.d("QuizPagerAdapter", "QuestionListSize: " + questionList.size());
resultFragment = ResultFragment.newInstance(((QuizFragment) fragment).answeredCorrectly.size());
return resultFragment;
}
return QuestionFragment.newInstance(questionList.get(position), position, getItemCount());
}
@Override
public int getItemCount() {
return questionList.size() + 1;
}
}
**ResultFragment.java: **
package com.example.project4;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class ResultFragment extends Fragment {
private TextView tvScore;
private int score;
public static ResultFragment newInstance(int score) {
ResultFragment fragment = new ResultFragment();
Bundle args = new Bundle();
args.putInt("SCORE", score);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_result, container, false);
if (getArguments() != null) {
score = getArguments().getInt("SCORE");
}
tvScore = view.findViewById(R.id.tvScore);
return view;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
tvScore.setText("Your Score: " + score);
}
public void updateScore(int newScore) {
score = newScore;
if (tvScore != null) {
tvScore.setText("Your Score: " + score);
}
}
}
I've already made sure that the score update and transition to the results page happen in sequence, and I've thoroughly verified my logic for determining if an answer is correct. But despite these efforts, the result is consistently one point less than expected when all questions are answered correctly.