Can't get the return value from a method that retrieves data from Firebase Realtime database to use it in...












2
















This question already has an answer here:




  • How to return DataSnapshot value as a result of a method?

    3 answers




I'm quite new to Firebase Realtime database. I'm working on an android app which requires data to be retrieved from Firebase Realtime DB. I've been able to retrieve data using the Firebase listener methods in most occasions but on one occasion, I've found it unable to get a value in the way that I want (I think because of the asynchronous nature).



SCENARIO:-



I have a data structure in Firebase Realtime Database as follows:



For rating:



database1



For users:



database2



I have a separate java class (Suggest.java) that has one simple method to get a list of users (not shown here since it is the basic implementation) and the method defined below to retrieve data from the above ratings node to a list:



public List<String> getMyUnratedPosts(final String currentUserId){
final List<String> currentUserUnratedPosts = new ArrayList<>();
DBRCurrentUnratedList = FirebaseDatabase.getInstance().getReference().child("adRat").child(currentUserId);
DBRCurrentUnratedList.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
AdRat adr = snapshot.getValue(AdRat.class);
int vr = adr.getViewRating();
if(vr < 1) {
currentUserUnratedPosts.add(adr.getAdId());
}
}
}

@Override
public void onCancelled(DatabaseError databaseError) {

}

});
return currentUserUnratedPosts;
}


The AdRat class defined above is just a class with attributes (and getters and setters) which matches the database node given above.



I'm creating an instance of this class (Suggest.java) in the onCreate() method of my activity. Then first I'm calling a method in which I'm simply getting a list of users (very similar to above method in which I get the ratings). Then the next line of code in my activity I use a for loop to get each user from the list I got and use that userId for the method shown above. For example, it would be as follows:



Suggest sj = new Suggest();
List<String> users = sj.getUsers();
for (final String mUser: users) {
//Just trying to use the user from above here
List<String> myUnratedItems = sj.getMyUnratedPosts(mUser);
Log.d(TAG, "list contains : " + myUnratedItems.toString());
}


PROBLEM :-



I do not get the intended result from the code when I run this. When I debug it, I will get null for the list of users. I think since the firebase methods are asynchronous they do not give the result exactly at the next line of code (that is the place where I need it) but gives the result a bit later (but then the program has run over the line of code in which I need that data).



MY OVERALL NECESSITY : -



Get the list of users to use it in the next line of code (for the next method).



I've gone through several questions in Stackoverflow in regard to this, but couldn't find an exact answer for this.



Please kindly explain as to why this happens and any workaround for this....



P.S. : - I'm new to stackoverflow, so please bear with me any mistakes done in composing the question. Thanks.










share|improve this question















marked as duplicate by Alex Mamo android
Users with the  android badge can single-handedly close android questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Nov 14 '18 at 12:11


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.



















  • Firebase requests are asynchronous, so your return currentUserUnratedPosts; will be alwayys 0 or null because you are trying to return something that has not been loaded yet.

    – Gastón Saillén
    Nov 14 '18 at 5:32











  • Please check the duplicate to see why do you have this behaviour and how can you solve this using a custom callback.

    – Alex Mamo
    Nov 14 '18 at 12:11











  • Hey @VandyWhite do mark the answer as correct by clicking the V type tick mark button next to the answer, and vote it up by clicking the up arrow button next to the answer, this helps people with similar question on Stack Overflow and I'd also appreciate that. Cheers!

    – PradyumanDixit
    Dec 26 '18 at 4:18
















2
















This question already has an answer here:




  • How to return DataSnapshot value as a result of a method?

    3 answers




I'm quite new to Firebase Realtime database. I'm working on an android app which requires data to be retrieved from Firebase Realtime DB. I've been able to retrieve data using the Firebase listener methods in most occasions but on one occasion, I've found it unable to get a value in the way that I want (I think because of the asynchronous nature).



SCENARIO:-



I have a data structure in Firebase Realtime Database as follows:



For rating:



database1



For users:



database2



I have a separate java class (Suggest.java) that has one simple method to get a list of users (not shown here since it is the basic implementation) and the method defined below to retrieve data from the above ratings node to a list:



public List<String> getMyUnratedPosts(final String currentUserId){
final List<String> currentUserUnratedPosts = new ArrayList<>();
DBRCurrentUnratedList = FirebaseDatabase.getInstance().getReference().child("adRat").child(currentUserId);
DBRCurrentUnratedList.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
AdRat adr = snapshot.getValue(AdRat.class);
int vr = adr.getViewRating();
if(vr < 1) {
currentUserUnratedPosts.add(adr.getAdId());
}
}
}

@Override
public void onCancelled(DatabaseError databaseError) {

}

});
return currentUserUnratedPosts;
}


The AdRat class defined above is just a class with attributes (and getters and setters) which matches the database node given above.



I'm creating an instance of this class (Suggest.java) in the onCreate() method of my activity. Then first I'm calling a method in which I'm simply getting a list of users (very similar to above method in which I get the ratings). Then the next line of code in my activity I use a for loop to get each user from the list I got and use that userId for the method shown above. For example, it would be as follows:



Suggest sj = new Suggest();
List<String> users = sj.getUsers();
for (final String mUser: users) {
//Just trying to use the user from above here
List<String> myUnratedItems = sj.getMyUnratedPosts(mUser);
Log.d(TAG, "list contains : " + myUnratedItems.toString());
}


PROBLEM :-



I do not get the intended result from the code when I run this. When I debug it, I will get null for the list of users. I think since the firebase methods are asynchronous they do not give the result exactly at the next line of code (that is the place where I need it) but gives the result a bit later (but then the program has run over the line of code in which I need that data).



MY OVERALL NECESSITY : -



Get the list of users to use it in the next line of code (for the next method).



I've gone through several questions in Stackoverflow in regard to this, but couldn't find an exact answer for this.



Please kindly explain as to why this happens and any workaround for this....



P.S. : - I'm new to stackoverflow, so please bear with me any mistakes done in composing the question. Thanks.










share|improve this question















marked as duplicate by Alex Mamo android
Users with the  android badge can single-handedly close android questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Nov 14 '18 at 12:11


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.



















  • Firebase requests are asynchronous, so your return currentUserUnratedPosts; will be alwayys 0 or null because you are trying to return something that has not been loaded yet.

    – Gastón Saillén
    Nov 14 '18 at 5:32











  • Please check the duplicate to see why do you have this behaviour and how can you solve this using a custom callback.

    – Alex Mamo
    Nov 14 '18 at 12:11











  • Hey @VandyWhite do mark the answer as correct by clicking the V type tick mark button next to the answer, and vote it up by clicking the up arrow button next to the answer, this helps people with similar question on Stack Overflow and I'd also appreciate that. Cheers!

    – PradyumanDixit
    Dec 26 '18 at 4:18














2












2








2









This question already has an answer here:




  • How to return DataSnapshot value as a result of a method?

    3 answers




I'm quite new to Firebase Realtime database. I'm working on an android app which requires data to be retrieved from Firebase Realtime DB. I've been able to retrieve data using the Firebase listener methods in most occasions but on one occasion, I've found it unable to get a value in the way that I want (I think because of the asynchronous nature).



SCENARIO:-



I have a data structure in Firebase Realtime Database as follows:



For rating:



database1



For users:



database2



I have a separate java class (Suggest.java) that has one simple method to get a list of users (not shown here since it is the basic implementation) and the method defined below to retrieve data from the above ratings node to a list:



public List<String> getMyUnratedPosts(final String currentUserId){
final List<String> currentUserUnratedPosts = new ArrayList<>();
DBRCurrentUnratedList = FirebaseDatabase.getInstance().getReference().child("adRat").child(currentUserId);
DBRCurrentUnratedList.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
AdRat adr = snapshot.getValue(AdRat.class);
int vr = adr.getViewRating();
if(vr < 1) {
currentUserUnratedPosts.add(adr.getAdId());
}
}
}

@Override
public void onCancelled(DatabaseError databaseError) {

}

});
return currentUserUnratedPosts;
}


The AdRat class defined above is just a class with attributes (and getters and setters) which matches the database node given above.



I'm creating an instance of this class (Suggest.java) in the onCreate() method of my activity. Then first I'm calling a method in which I'm simply getting a list of users (very similar to above method in which I get the ratings). Then the next line of code in my activity I use a for loop to get each user from the list I got and use that userId for the method shown above. For example, it would be as follows:



Suggest sj = new Suggest();
List<String> users = sj.getUsers();
for (final String mUser: users) {
//Just trying to use the user from above here
List<String> myUnratedItems = sj.getMyUnratedPosts(mUser);
Log.d(TAG, "list contains : " + myUnratedItems.toString());
}


PROBLEM :-



I do not get the intended result from the code when I run this. When I debug it, I will get null for the list of users. I think since the firebase methods are asynchronous they do not give the result exactly at the next line of code (that is the place where I need it) but gives the result a bit later (but then the program has run over the line of code in which I need that data).



MY OVERALL NECESSITY : -



Get the list of users to use it in the next line of code (for the next method).



I've gone through several questions in Stackoverflow in regard to this, but couldn't find an exact answer for this.



Please kindly explain as to why this happens and any workaround for this....



P.S. : - I'm new to stackoverflow, so please bear with me any mistakes done in composing the question. Thanks.










share|improve this question

















This question already has an answer here:




  • How to return DataSnapshot value as a result of a method?

    3 answers




I'm quite new to Firebase Realtime database. I'm working on an android app which requires data to be retrieved from Firebase Realtime DB. I've been able to retrieve data using the Firebase listener methods in most occasions but on one occasion, I've found it unable to get a value in the way that I want (I think because of the asynchronous nature).



SCENARIO:-



I have a data structure in Firebase Realtime Database as follows:



For rating:



database1



For users:



database2



I have a separate java class (Suggest.java) that has one simple method to get a list of users (not shown here since it is the basic implementation) and the method defined below to retrieve data from the above ratings node to a list:



public List<String> getMyUnratedPosts(final String currentUserId){
final List<String> currentUserUnratedPosts = new ArrayList<>();
DBRCurrentUnratedList = FirebaseDatabase.getInstance().getReference().child("adRat").child(currentUserId);
DBRCurrentUnratedList.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
AdRat adr = snapshot.getValue(AdRat.class);
int vr = adr.getViewRating();
if(vr < 1) {
currentUserUnratedPosts.add(adr.getAdId());
}
}
}

@Override
public void onCancelled(DatabaseError databaseError) {

}

});
return currentUserUnratedPosts;
}


The AdRat class defined above is just a class with attributes (and getters and setters) which matches the database node given above.



I'm creating an instance of this class (Suggest.java) in the onCreate() method of my activity. Then first I'm calling a method in which I'm simply getting a list of users (very similar to above method in which I get the ratings). Then the next line of code in my activity I use a for loop to get each user from the list I got and use that userId for the method shown above. For example, it would be as follows:



Suggest sj = new Suggest();
List<String> users = sj.getUsers();
for (final String mUser: users) {
//Just trying to use the user from above here
List<String> myUnratedItems = sj.getMyUnratedPosts(mUser);
Log.d(TAG, "list contains : " + myUnratedItems.toString());
}


PROBLEM :-



I do not get the intended result from the code when I run this. When I debug it, I will get null for the list of users. I think since the firebase methods are asynchronous they do not give the result exactly at the next line of code (that is the place where I need it) but gives the result a bit later (but then the program has run over the line of code in which I need that data).



MY OVERALL NECESSITY : -



Get the list of users to use it in the next line of code (for the next method).



I've gone through several questions in Stackoverflow in regard to this, but couldn't find an exact answer for this.



Please kindly explain as to why this happens and any workaround for this....



P.S. : - I'm new to stackoverflow, so please bear with me any mistakes done in composing the question. Thanks.





This question already has an answer here:




  • How to return DataSnapshot value as a result of a method?

    3 answers








java android firebase firebase-realtime-database






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 14 '18 at 6:23









PradyumanDixit

2,1812819




2,1812819










asked Nov 14 '18 at 4:29









Vandy WhiteVandy White

112




112




marked as duplicate by Alex Mamo android
Users with the  android badge can single-handedly close android questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Nov 14 '18 at 12:11


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.









marked as duplicate by Alex Mamo android
Users with the  android badge can single-handedly close android questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Nov 14 '18 at 12:11


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.















  • Firebase requests are asynchronous, so your return currentUserUnratedPosts; will be alwayys 0 or null because you are trying to return something that has not been loaded yet.

    – Gastón Saillén
    Nov 14 '18 at 5:32











  • Please check the duplicate to see why do you have this behaviour and how can you solve this using a custom callback.

    – Alex Mamo
    Nov 14 '18 at 12:11











  • Hey @VandyWhite do mark the answer as correct by clicking the V type tick mark button next to the answer, and vote it up by clicking the up arrow button next to the answer, this helps people with similar question on Stack Overflow and I'd also appreciate that. Cheers!

    – PradyumanDixit
    Dec 26 '18 at 4:18



















  • Firebase requests are asynchronous, so your return currentUserUnratedPosts; will be alwayys 0 or null because you are trying to return something that has not been loaded yet.

    – Gastón Saillén
    Nov 14 '18 at 5:32











  • Please check the duplicate to see why do you have this behaviour and how can you solve this using a custom callback.

    – Alex Mamo
    Nov 14 '18 at 12:11











  • Hey @VandyWhite do mark the answer as correct by clicking the V type tick mark button next to the answer, and vote it up by clicking the up arrow button next to the answer, this helps people with similar question on Stack Overflow and I'd also appreciate that. Cheers!

    – PradyumanDixit
    Dec 26 '18 at 4:18

















Firebase requests are asynchronous, so your return currentUserUnratedPosts; will be alwayys 0 or null because you are trying to return something that has not been loaded yet.

– Gastón Saillén
Nov 14 '18 at 5:32





Firebase requests are asynchronous, so your return currentUserUnratedPosts; will be alwayys 0 or null because you are trying to return something that has not been loaded yet.

– Gastón Saillén
Nov 14 '18 at 5:32













Please check the duplicate to see why do you have this behaviour and how can you solve this using a custom callback.

– Alex Mamo
Nov 14 '18 at 12:11





Please check the duplicate to see why do you have this behaviour and how can you solve this using a custom callback.

– Alex Mamo
Nov 14 '18 at 12:11













Hey @VandyWhite do mark the answer as correct by clicking the V type tick mark button next to the answer, and vote it up by clicking the up arrow button next to the answer, this helps people with similar question on Stack Overflow and I'd also appreciate that. Cheers!

– PradyumanDixit
Dec 26 '18 at 4:18





Hey @VandyWhite do mark the answer as correct by clicking the V type tick mark button next to the answer, and vote it up by clicking the up arrow button next to the answer, this helps people with similar question on Stack Overflow and I'd also appreciate that. Cheers!

– PradyumanDixit
Dec 26 '18 at 4:18












2 Answers
2






active

oldest

votes


















0














Indeed, the eventListeners and calls to Firebase have asynchronous behaviour and thus you have correctly understood your problem.



Unfortunately the solution I have(which almost certainly works) is that you may have to change your approach because of this.



So you should go for an event driven approach. Hence, instead of "wait for the data to come and and then do my thing", you should "when the data comes in, do my thing".



Meaning according to your problem, firs you should retrieve the list of users from the Firebase as you have correctly done in the onDataChange() of valueEventListener, and beneath it, do your thing which you intend to do.



The problem is that since Firebase has asynchronous calls, your data gets printed before it can retrieved, which obviously would be null if you haven't initialised it to something else. So all further operations that you do, occur on null.



So it would be better for you to execute your method or code inside the valueEventListener itself.



Something like this in your given code:



public List<String> getMyUnratedPosts(final String currentUserId){
final List<String> currentUserUnratedPosts = new ArrayList<>();
DBRCurrentUnratedList = FirebaseDatabase.getInstance().getReference().child("adRat").child(currentUserId);
DBRCurrentUnratedList.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
AdRat adr = snapshot.getValue(AdRat.class);
int vr = adr.getViewRating();
if(vr < 1) {
currentUserUnratedPosts.add(adr.getAdId());
}
}

// do your thing right here
}

@Override
public void onCancelled(DatabaseError databaseError) {

}

});
return currentUserUnratedPosts;
}


Other than that, one more approach I found, when I searched though, is Task.await(). But, I won't be counting on it.



You may read more about that here:



StackOverflow Question



StackOverflow Answer






share|improve this answer































    0














    You're exactly right in that it is caused by the asynchronicity of the Firebase calls. The kind of system you'll most likely want to employ is one in which you "subscribe" to know when calls have completed. You can use a callback function, or some other method, such as adding a field/piece of data to a list, and having another data structure periodically check the list for updates, in order to know when the async call has completed.



    Your flow will probably be something like this:




    1. "subscribe" to the asynchronous data structure

    2. tell asynchronous data structure to execute

    3. on completion of the asynchronous call, perform some action.


    I'd recommend looking at the following link on Asynchronous callbacks in Java from Geeksforgeeks: https://www.geeksforgeeks.org/asynchronous-synchronous-callbacks-java/






    share|improve this answer






























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      0














      Indeed, the eventListeners and calls to Firebase have asynchronous behaviour and thus you have correctly understood your problem.



      Unfortunately the solution I have(which almost certainly works) is that you may have to change your approach because of this.



      So you should go for an event driven approach. Hence, instead of "wait for the data to come and and then do my thing", you should "when the data comes in, do my thing".



      Meaning according to your problem, firs you should retrieve the list of users from the Firebase as you have correctly done in the onDataChange() of valueEventListener, and beneath it, do your thing which you intend to do.



      The problem is that since Firebase has asynchronous calls, your data gets printed before it can retrieved, which obviously would be null if you haven't initialised it to something else. So all further operations that you do, occur on null.



      So it would be better for you to execute your method or code inside the valueEventListener itself.



      Something like this in your given code:



      public List<String> getMyUnratedPosts(final String currentUserId){
      final List<String> currentUserUnratedPosts = new ArrayList<>();
      DBRCurrentUnratedList = FirebaseDatabase.getInstance().getReference().child("adRat").child(currentUserId);
      DBRCurrentUnratedList.addValueEventListener(new ValueEventListener() {
      @Override
      public void onDataChange(DataSnapshot dataSnapshot) {
      for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
      AdRat adr = snapshot.getValue(AdRat.class);
      int vr = adr.getViewRating();
      if(vr < 1) {
      currentUserUnratedPosts.add(adr.getAdId());
      }
      }

      // do your thing right here
      }

      @Override
      public void onCancelled(DatabaseError databaseError) {

      }

      });
      return currentUserUnratedPosts;
      }


      Other than that, one more approach I found, when I searched though, is Task.await(). But, I won't be counting on it.



      You may read more about that here:



      StackOverflow Question



      StackOverflow Answer






      share|improve this answer




























        0














        Indeed, the eventListeners and calls to Firebase have asynchronous behaviour and thus you have correctly understood your problem.



        Unfortunately the solution I have(which almost certainly works) is that you may have to change your approach because of this.



        So you should go for an event driven approach. Hence, instead of "wait for the data to come and and then do my thing", you should "when the data comes in, do my thing".



        Meaning according to your problem, firs you should retrieve the list of users from the Firebase as you have correctly done in the onDataChange() of valueEventListener, and beneath it, do your thing which you intend to do.



        The problem is that since Firebase has asynchronous calls, your data gets printed before it can retrieved, which obviously would be null if you haven't initialised it to something else. So all further operations that you do, occur on null.



        So it would be better for you to execute your method or code inside the valueEventListener itself.



        Something like this in your given code:



        public List<String> getMyUnratedPosts(final String currentUserId){
        final List<String> currentUserUnratedPosts = new ArrayList<>();
        DBRCurrentUnratedList = FirebaseDatabase.getInstance().getReference().child("adRat").child(currentUserId);
        DBRCurrentUnratedList.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
        for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
        AdRat adr = snapshot.getValue(AdRat.class);
        int vr = adr.getViewRating();
        if(vr < 1) {
        currentUserUnratedPosts.add(adr.getAdId());
        }
        }

        // do your thing right here
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }

        });
        return currentUserUnratedPosts;
        }


        Other than that, one more approach I found, when I searched though, is Task.await(). But, I won't be counting on it.



        You may read more about that here:



        StackOverflow Question



        StackOverflow Answer






        share|improve this answer


























          0












          0








          0







          Indeed, the eventListeners and calls to Firebase have asynchronous behaviour and thus you have correctly understood your problem.



          Unfortunately the solution I have(which almost certainly works) is that you may have to change your approach because of this.



          So you should go for an event driven approach. Hence, instead of "wait for the data to come and and then do my thing", you should "when the data comes in, do my thing".



          Meaning according to your problem, firs you should retrieve the list of users from the Firebase as you have correctly done in the onDataChange() of valueEventListener, and beneath it, do your thing which you intend to do.



          The problem is that since Firebase has asynchronous calls, your data gets printed before it can retrieved, which obviously would be null if you haven't initialised it to something else. So all further operations that you do, occur on null.



          So it would be better for you to execute your method or code inside the valueEventListener itself.



          Something like this in your given code:



          public List<String> getMyUnratedPosts(final String currentUserId){
          final List<String> currentUserUnratedPosts = new ArrayList<>();
          DBRCurrentUnratedList = FirebaseDatabase.getInstance().getReference().child("adRat").child(currentUserId);
          DBRCurrentUnratedList.addValueEventListener(new ValueEventListener() {
          @Override
          public void onDataChange(DataSnapshot dataSnapshot) {
          for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
          AdRat adr = snapshot.getValue(AdRat.class);
          int vr = adr.getViewRating();
          if(vr < 1) {
          currentUserUnratedPosts.add(adr.getAdId());
          }
          }

          // do your thing right here
          }

          @Override
          public void onCancelled(DatabaseError databaseError) {

          }

          });
          return currentUserUnratedPosts;
          }


          Other than that, one more approach I found, when I searched though, is Task.await(). But, I won't be counting on it.



          You may read more about that here:



          StackOverflow Question



          StackOverflow Answer






          share|improve this answer













          Indeed, the eventListeners and calls to Firebase have asynchronous behaviour and thus you have correctly understood your problem.



          Unfortunately the solution I have(which almost certainly works) is that you may have to change your approach because of this.



          So you should go for an event driven approach. Hence, instead of "wait for the data to come and and then do my thing", you should "when the data comes in, do my thing".



          Meaning according to your problem, firs you should retrieve the list of users from the Firebase as you have correctly done in the onDataChange() of valueEventListener, and beneath it, do your thing which you intend to do.



          The problem is that since Firebase has asynchronous calls, your data gets printed before it can retrieved, which obviously would be null if you haven't initialised it to something else. So all further operations that you do, occur on null.



          So it would be better for you to execute your method or code inside the valueEventListener itself.



          Something like this in your given code:



          public List<String> getMyUnratedPosts(final String currentUserId){
          final List<String> currentUserUnratedPosts = new ArrayList<>();
          DBRCurrentUnratedList = FirebaseDatabase.getInstance().getReference().child("adRat").child(currentUserId);
          DBRCurrentUnratedList.addValueEventListener(new ValueEventListener() {
          @Override
          public void onDataChange(DataSnapshot dataSnapshot) {
          for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
          AdRat adr = snapshot.getValue(AdRat.class);
          int vr = adr.getViewRating();
          if(vr < 1) {
          currentUserUnratedPosts.add(adr.getAdId());
          }
          }

          // do your thing right here
          }

          @Override
          public void onCancelled(DatabaseError databaseError) {

          }

          });
          return currentUserUnratedPosts;
          }


          Other than that, one more approach I found, when I searched though, is Task.await(). But, I won't be counting on it.



          You may read more about that here:



          StackOverflow Question



          StackOverflow Answer







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 14 '18 at 4:56









          PradyumanDixitPradyumanDixit

          2,1812819




          2,1812819

























              0














              You're exactly right in that it is caused by the asynchronicity of the Firebase calls. The kind of system you'll most likely want to employ is one in which you "subscribe" to know when calls have completed. You can use a callback function, or some other method, such as adding a field/piece of data to a list, and having another data structure periodically check the list for updates, in order to know when the async call has completed.



              Your flow will probably be something like this:




              1. "subscribe" to the asynchronous data structure

              2. tell asynchronous data structure to execute

              3. on completion of the asynchronous call, perform some action.


              I'd recommend looking at the following link on Asynchronous callbacks in Java from Geeksforgeeks: https://www.geeksforgeeks.org/asynchronous-synchronous-callbacks-java/






              share|improve this answer




























                0














                You're exactly right in that it is caused by the asynchronicity of the Firebase calls. The kind of system you'll most likely want to employ is one in which you "subscribe" to know when calls have completed. You can use a callback function, or some other method, such as adding a field/piece of data to a list, and having another data structure periodically check the list for updates, in order to know when the async call has completed.



                Your flow will probably be something like this:




                1. "subscribe" to the asynchronous data structure

                2. tell asynchronous data structure to execute

                3. on completion of the asynchronous call, perform some action.


                I'd recommend looking at the following link on Asynchronous callbacks in Java from Geeksforgeeks: https://www.geeksforgeeks.org/asynchronous-synchronous-callbacks-java/






                share|improve this answer


























                  0












                  0








                  0







                  You're exactly right in that it is caused by the asynchronicity of the Firebase calls. The kind of system you'll most likely want to employ is one in which you "subscribe" to know when calls have completed. You can use a callback function, or some other method, such as adding a field/piece of data to a list, and having another data structure periodically check the list for updates, in order to know when the async call has completed.



                  Your flow will probably be something like this:




                  1. "subscribe" to the asynchronous data structure

                  2. tell asynchronous data structure to execute

                  3. on completion of the asynchronous call, perform some action.


                  I'd recommend looking at the following link on Asynchronous callbacks in Java from Geeksforgeeks: https://www.geeksforgeeks.org/asynchronous-synchronous-callbacks-java/






                  share|improve this answer













                  You're exactly right in that it is caused by the asynchronicity of the Firebase calls. The kind of system you'll most likely want to employ is one in which you "subscribe" to know when calls have completed. You can use a callback function, or some other method, such as adding a field/piece of data to a list, and having another data structure periodically check the list for updates, in order to know when the async call has completed.



                  Your flow will probably be something like this:




                  1. "subscribe" to the asynchronous data structure

                  2. tell asynchronous data structure to execute

                  3. on completion of the asynchronous call, perform some action.


                  I'd recommend looking at the following link on Asynchronous callbacks in Java from Geeksforgeeks: https://www.geeksforgeeks.org/asynchronous-synchronous-callbacks-java/







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 14 '18 at 4:58









                  loganrussell48loganrussell48

                  84310




                  84310















                      Popular posts from this blog

                      The Sandy Post

                      Danny Elfman

                      Pages that link to "Head v. Amoskeag Manufacturing Co."