-1

I am currently doing some school android project and I need help.I have variable that takes some value in database listener,and I have to use that value outside listener.Can you please help me to find way to correct initialization and using that variable.Thank you My code is below

 DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("user");
            ref.addListenerForSingleValueEvent(
                    new ValueEventListener() {
                        @Override
                        public void onDataChange(DataSnapshot dataSnapshot) {
                            //Get map of users in datasnapshot

                           names= getAllNames((Map<String,Object>) dataSnapshot.getValue());

                        }

                        @Override
                        public void onCancelled(DatabaseError databaseError) {
                            //handle databaseError
                        }
                    });
         String p=  names.get(1);

this method getAllNames is working fine,I tested it .P in this case is null because it is usingf "names" outside listener and variable "names" is problem,but in listener it shows correct value.

  • Setting a variable inside such a listener and using it outside is not possible. The code in the listener is run in another thread at another time. Your code simply sets the listener and directly moves on to using the variable. That's why it is null. You must use the retrieved values inside the listener. – Seelenvirtuose Jun 02 '18 at 15:26
  • I recommend you see the last part of my anwser from this **[post](https://stackoverflow.com/questions/47847694/how-to-return-datasnapshot-value-as-a-result-of-a-method/47853774)** and also take a look at this **[video](https://www.youtube.com/watch?v=OvDZVV5CbQg)**. – Alex Mamo Jun 04 '18 at 16:37
  • I watched your tutorial.It is great.Gave you subscribe and like ,thank you a lot . – lana zunic Jun 14 '18 at 13:43

1 Answers1

0

This is against nature of async.

It'd better if you chain your next method / logic in onDataChange instead of accessing it from outsides.

However, you can do it with Task

public Task<List<String>> getNames() {
TaskCompletionSource<String> task = new TaskCompletionSource<>();
DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("user");
            ref.addListenerForSingleValueEvent(
                    new ValueEventListener() {
                        @Override
                        public void onDataChange(DataSnapshot dataSnapshot) {
                            //Get map of users in datasnapshot

                           task.setResult(getAllNames((Map<String,Object>) dataSnapshot.getValue()));

                        }

                        @Override
                        public void onCancelled(DatabaseError databaseError) {
                            //handle databaseError
                            task.setException(new RuntimeException());
                        }
                    });
    return task.getTask()

}

Now reuse it in your method:

Task<List<String>> task = getNames();
List<String> names = Tasks.await(task); // This will block till done
Mạnh Quyết Nguyễn
  • 17,677
  • 1
  • 23
  • 51