Skip to content

How to get random qestion from firebase firestore database

i m making a quiz app, in which i have categories, when i choose a category, qestions start coming from firebase firestore database , in each category i have 10 qestion in database , i want that all qestions load from firebase data base and comes in random order each time ,

but my problem here is all qestions is not loading , some times load 5 ,sometimes 7 and this random order carries on..

i don’t have much knowlegde about firebase database below is the code what i have tried

my QuizzActivity code

public class QuizActivity extends AppCompatActivity {

ActivityQuizBinding binding;

ArrayList<Questions> qestions;

Questions question;

CountDownTimer timer;

FirebaseFirestore database;

int correctAnswer = 0;

int index = 0;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);



    binding = ActivityQuizBinding.inflate(getLayoutInflater());
    setContentView(binding.getRoot());

    qestions = new ArrayList<>();
    database = FirebaseFirestore.getInstance();

  final   String cateGoryID = getIntent().getStringExtra("categoryID");

    Random random = new Random();
  final   int rand = random.nextInt(10);

    database.collection("categories")
            .document(cateGoryID)
            .collection("questions")
            .whereGreaterThanOrEqualTo("index",rand)
            .orderBy("index")
            .limit(5)
            .get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
        @Override
        public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
            if (queryDocumentSnapshots.getDocuments().size()<5){

                database.collection("categories")
                        .document(cateGoryID)
                        .collection("questions")
                        .whereLessThanOrEqualTo("index",rand)
                        .orderBy("index")
                        .limit(5)
                        .get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
                    @Override
                    public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
                        for (DocumentSnapshot snapshot : queryDocumentSnapshots){
                                Questions questions = snapshot.toObject(Questions.class);
                                qestions.add(questions);
                            }
                        setNextQestions();

                    }
                });


            } else {

                for (DocumentSnapshot snapshot : queryDocumentSnapshots){
                    Questions questions = snapshot.toObject(Questions.class);
                    qestions.add(questions);
                }
                setNextQestions();


            }
        }
    });


     resetTimer();

}

void resetTimer(){

    timer = new CountDownTimer(30000,1000) {
        @Override
        public void onTick(long l) {

            binding.timer.setText(String.valueOf(l/1000));

        }

        @Override
        public void onFinish() {

        }
    };
}

public void CheckAnwer(TextView textView){
    String selectAnswer = textView.getText().toString();
    if(selectAnswer.equals(question.getAnswer())){
        correctAnswer++ ;
        textView.setBackground(getResources().getDrawable(R.drawable.option_right));
    }
    else{
        showAnswer();
        textView.setBackground(getResources().getDrawable(R.drawable.option_wrong));
    }
}


@Override
public void onBackPressed() {
    new AlertDialog.Builder(QuizActivity.this)
            .setIcon(R.drawable.ic_baseline_person_24)
            .setMessage("Are you sure want to Quit Game")
            .setPositiveButton("yes", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    Intent in = new Intent(QuizActivity.this,MainActivity.class);
                    startActivity(in);
                    finish();
                }
            }).setNegativeButton("No", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialogInterface, int i) {
            dialogInterface.dismiss();
        }
    }).create().show();

}


public void setNextQestions() {

    if(timer != null){
        timer.cancel();
    }




    timer.start();



    if (index < qestions.size()) {

        binding.qestioncounter.setText(String.format("%d/%d",(index+1),qestions.size()));
         question = qestions.get(index);
        binding.qestions.setText(question.getQestion());
        binding.option1.setText(question.getOption1());
        binding.option2.setText(question.getOption2());
        binding.option3.setText(question.getOption3());
        binding.option4.setText(question.getOption4());

    }
}

void reset(){
    binding.option1.setBackground(getResources().getDrawable(R.drawable.option_unselected));
    binding.option2.setBackground(getResources().getDrawable(R.drawable.option_unselected));
    binding.option3.setBackground(getResources().getDrawable(R.drawable.option_unselected));
    binding.option4.setBackground(getResources().getDrawable(R.drawable.option_unselected));
}


void showAnswer(){
    if (question.getAnswer().equals(binding.option1.getText().toString()))
        binding.option1.setBackground(getResources().getDrawable(R.drawable.option_right));

    else  if (question.getAnswer().equals(binding.option2.getText().toString()))
        binding.option2.setBackground(getResources().getDrawable(R.drawable.option_right));

    else  if (question.getAnswer().equals(binding.option3.getText().toString()))
        binding.option3.setBackground(getResources().getDrawable(R.drawable.option_right));

    else  if (question.getAnswer().equals(binding.option4.getText().toString()))
        binding.option4.setBackground(getResources().getDrawable(R.drawable.option_right));

}

public void onClick(View view){
    switch (view.getId()){

        case R.id.option_1:

        case R.id.option_2:
        case R.id.option_3:
        case R.id.option_4:
            if(timer != null){
                timer.cancel();
            }
            TextView selected = (TextView) view;
            CheckAnwer(selected);
            break;

        case R.id.next_btn:
            // reset();
            if (index < qestions.size()){
                reset();
            index++;
            setNextQestions();}
            else {

                Toast.makeText(this, "Quiz Finsished", Toast.LENGTH_SHORT).show();
                Intent in = new Intent(QuizActivity.this,ResultActivity.class);
                in.putExtra("correct_answer",correctAnswer);
                in.putExtra("total",qestions.size());
                startActivity(in);

            }
            break;







    }
}

Answer

The easiest thing to do is load all questions without using random and after adding all questions to qestions array list then shuffle it.

for (DocumentSnapshot snapshot : queryDocumentSnapshots){
    Questions questions = snapshot.toObject(Questions.class);
    qestions.add(questions);
}
Collections.shuffle(questions);
setNextQestions();

Make changes like this.

case R.id.next_btn:
    setNextQestions();
    break;

setNextQestions method

public void setNextQestions() {
    if(timer != null){
        timer.cancel();
    }

    timer.start();

if (index < qestions.size()) {
    binding.qestioncounter.setText(String.format("%d/%d",(index+1),qestions.size()));
    question = qestions.get(index);
    binding.qestions.setText(question.getQestion());
    binding.option1.setText(question.getOption1());
    binding.option2.setText(question.getOption2());
    binding.option3.setText(question.getOption3());
    binding.option4.setText(question.getOption4());
    index++;
}
else {
    reset();
    Toast.makeText(this, "Quiz Finsished", Toast.LENGTH_SHORT).show();
    Intent in = new Intent(QuizActivity.this,ResultActivity.class);
    in.putExtra("correct_answer",correctAnswer);
    in.putExtra("total",qestions.size());
    startActivity(in);
}
}