In my app I use the firebase database. There are questions and the corresponding comments stored in seperat nodes. Now I try to get the questions with the one listener and access the comments with a second listener. Unfortunately I‘m confused by their behavior: the recyclerView always gets an empty questionsList, like the second listener is skipped. But after the recyclerView got the list and the adapter is set up, my LogCat starts printing the questions and the comment information. But why is the recyclerView populated and used before the for loop that processes the data has finished?

The method to fetch the information:

private void getQuestionsFromDatabase() {

    mQuestions.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {

            questionList = new ArrayList<>();
            for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {

                final String title = dataSnapshot1.child("title").getValue().toString();
                final String question = dataSnapshot1.child("question").getValue().toString();
                final String commentId = dataSnapshot1.child("commentId").getValue().toString();

                mComments.child(commentId).addListenerForSingleValueEvent(new ValueEventListener() {
                    @Override
                    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

                        count = dataSnapshot.getChildrenCount();

                        QuestionModel questionModel = new QuestionModel(title, question, commentId, String.valueOf(count));
                        questionList.add(questionModel);

                    }

                    @Override
                    public void onCancelled(@NonNull DatabaseError databaseError) {

                    }
                });

            }

            Log.d("questionList length: ", String.valueOf(questionList.size()));
            recyclerViewAdapter = new RecyclerViewQuestionAdapter(questionList, getActivity());
            recyclerViewlayoutManager = new LinearLayoutManager(getActivity());
            recyclerView.setLayoutManager(recyclerViewlayoutManager);
            recyclerView.setAdapter(recyclerViewAdapter);

        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {

        }

    });

}
Answer

It is used before, because the onDataChange is asynchronous, which means that the compiler will not wait until data is fetched from the database, instead it will execute the code after the listener. Therefore to solve your problem, you should do the following:

                mComments.child(commentId).addListenerForSingleValueEvent(new ValueEventListener() {
                @Override
                public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

                    count = dataSnapshot.getChildrenCount();

                    QuestionModel questionModel = new QuestionModel(title, question, commentId, String.valueOf(count));
                    questionList.add(questionModel);
                    Log.d("questionList length: ", String.valueOf(questionList.size()));
                    recyclerViewAdapter = new RecyclerViewQuestionAdapter(questionList, getActivity());
                    recyclerViewlayoutManager = new LinearLayoutManager(getActivity());
                    recyclerView.setLayoutManager(recyclerViewlayoutManager);
                    recyclerView.setAdapter(recyclerViewAdapter);

                }

                @Override
                public void onCancelled(@NonNull DatabaseError databaseError) {

                }
            });

        }
  • 1
Reply Report
      • 1
    • Ah okay, that sounds logical! I thought about that solution as well, but then it doesn’t list all results at once but one after the other when they‘re loaded. Do you have an idea to avoid that?
      • 1
    • Can you explain the usage of a progressbar? Which is the point where I know that the data is retrieved and how do I prevent to show the results so far when I‘m not showing them in the end but always update it? Okay, so is it incorrect to use the SingleValueEvent here?
      • 1
    • because addvalueeventlistener will keep listening to change in the database, thus it will be able to retrieve the data all at once

Warm tip !!!

This article is reproduced from Stack Exchange / Stack Overflow, please click

Trending Tags

Related Questions