0

While trying to retrieve data from Firestore observed that return value always comes as 0. Can somebody please advise how this can be corrected?

public List<Passion> getPassionvalue() {
  List<Passion> msglist = new ArrayList<>();
  CollectionReference col_ref = this.get_collection_firestore("Passion")
  col_ref
          .get()
          .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
              @Override
              public void onComplete(@NonNull Task<QuerySnapshot> task) {
                  if(task.isSuccessful())
                  {
                      for(QueryDocumentSnapshot document : task.getResult())
                      {

                          Passion passion =document.toObject(Passion.class);
                          msglist.add(passion);
                      }
                  }
                  else {
                  }
              }
          });
  return msglist; // return value is always 0 as if no data.
 }

EDIT

Method in Repository Class:

public List<Passion> downloadpassion()
  {
    return fsDB.getPassionvalue();
  }

Method in ViewModel Class:

public List<Passion> downloadpassionlist()
{
   return mPassionRepository.downloadpassion();
}
Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
Sukesh Saxena
  • 201
  • 2
  • 18
  • You mean the size of the list is zero? We need to see the data structure in Firebase. – TheWanderer Oct 30 '18 at 12:35
  • @Wanderer Thanx for responding. The data structure is just having one Collection and multiple document with single field called passion. There is no issue in data structure. Since when i am checking 'for loop', I find data there. Its just happen that method is not waiting for 'for loop' to finish and then return it. It is just skipping the for loop altogether and going to last statement as if it is putting on another thread. Hope I am able to clarify. If not let me know. Rgds – Sukesh Saxena Oct 30 '18 at 12:44
  • Oh of course. This is the danger of asynchronous tasks. Give me a bit and I'll write an answer. – TheWanderer Oct 30 '18 at 12:53

1 Answers1

2

Internet requests in Android have to be asynchronous, to avoid freezing the UI. Since Firebase is an internet-based service, it has the same restriction/requirement.

When you use listeners in Java, the program won't wait until that listener is called before continuing past it, since that would defeat the purpose of being asynchronous.

Because of this, you can't use a simple getter method that directly returns a value. Instead, you need to use your own listener.

Create a new interface (either inside the file you're editing or as its own class):

public interface OnPassionsFilledListener {
    void onPassionsFilled(ArrayList<Passion> passions);
    void onError(Exception taskException);
}

Then, modify your method a little:

public void getPassionValue(OnPassionsFilledListener listener) {
    get_collection_firestore("Passion")
            .get()
            .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                @Override
                public void onComplete(@NonNull Task<QuerySnapshot> task) {
                    if (task.isSuccessful()) {
                        ArrayList<Passion> passions = new ArrayList<>();

                        for (QueryDocumentSnapshot document : task.getResult()) {
                            Passion passion = document.toObject(Passion.class);
                            passions.add(passion);
                        }

                        listener.onPassionsFilled(passions);
                    } else {
                        listener.onError(task.getException());
                    }
                }
            });
}

To call your method:

getPassionValue(new OnPassionsFilledListener() {
    @Override
    public void onPassionsFilled(ArrayList<Passion> passions) {
        //handle the list
    }

    @Override
    public void onError(Exception taskException) {
        //handle the error
    }
});

BTW, in Java, methods and variable names use camelCase (not underscore_case), and classes use TitleCase. You don't have to follow these guidelines, but they make it easier for others to read your code.

TheWanderer
  • 16,775
  • 6
  • 49
  • 63
  • @Wanderer Thanks for your answer. Values available in onPassionsFilled is required in below method for further use public List downloadpassion() { return fsDB.getPassionvalue(); } How can we do this? – Sukesh Saxena Oct 30 '18 at 13:40
  • You need to restructure your code to take into account the asynchronous nature on network calls. – TheWanderer Oct 30 '18 at 13:43
  • I do implement callback but stuck on how to send value in the parent method so that it can be returned in ViewModel . Can you advise please.. – Sukesh Saxena Oct 30 '18 at 13:49
  • Edit my Post to include methods in ViewModel & Repository class – Sukesh Saxena Oct 30 '18 at 13:54
  • @Wanderer is there any other way that can run as single thread for execution of this method? – Sukesh Saxena Oct 31 '18 at 03:03