2

I'm new to Firebase and working on simple project. I have a method to get a list of teachers from Firebase and add their emails to an ArrayList and return.

public ArrayList<String> getTeacherList() {
    temp = new ArrayList();

    Firebase node = ref.child("teachers");
    Query query = node.orderByChild("subject").equalTo(selected_subject);

    query.addChildEventListener(new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String s) {

            Map<String,Object> value = (Map<String, Object>) dataSnapshot.getValue();
            Log.d("TEACHER"," "+value.toString());

            Iterator entries = value.entrySet().iterator();
            while (entries.hasNext()) {
                Map.Entry thisEntry = (Map.Entry) entries.next();
                String key = (String) thisEntry.getKey();
                Object data = thisEntry.getValue();

                if(key.equals("email")) {
                    temp.add(data.toString());
                    Log.d("ENTRY",": DATA "+data.toString());
                }
            }
            
        }

        @Override
        public void onChildChanged(DataSnapshot dataSnapshot, String s) {

        }

        @Override
        public void onChildRemoved(DataSnapshot dataSnapshot) {

        }

        @Override
        public void onChildMoved(DataSnapshot dataSnapshot, String s) {

        }

        @Override
        public void onCancelled(FirebaseError firebaseError) {

        }
    });


    Log.d("RETURN", temp.toString());
    return temp;
}

This method is working fine. But the problem is this returns the temp variable before completing adding child.

For example my Android Monitor is like that :

D/RETURN: []

D/TEACHER: {number=1, name=Teacher, email=teacher@new.lk, subject=Physics}

D/ENTRY: : DATA teacher@new.lk

Is there any way to wait until complete thatonChildAdded method..?

=========================================================================

I tried in this way also. But then it stopped at inside method.

Even it didn't go to Log.d("TEACHER", " " + value.toString()); tag here.

public  ArrayList getTeacherList() throws InterruptedException {
    temp = new ArrayList();

    Firebase node = ref.child("teachers");
    Query query = node.orderByChild("subject").equalTo(selected_subject);

    semaphore = new Semaphore(0);

    query.addChildEventListener(new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String s) {

            Map<String, Object> value = (Map<String, Object>) dataSnapshot.getValue();
            Log.d("TEACHER", " " + value.toString());

            Iterator entries = value.entrySet().iterator();
            while (entries.hasNext()) {
                Map.Entry thisEntry = (Map.Entry) entries.next();
                String key = (String) thisEntry.getKey();
                Object data = thisEntry.getValue();

                if (key.equals("email")) {
                    setArrayList(data.toString());
                    Log.d("ENTRY", ": DATA " + data.toString());
                }
            }
            semaphore.release();
        }

        @Override
        public void onChildChanged(DataSnapshot dataSnapshot, String s) {

        }

        @Override
        public void onChildRemoved(DataSnapshot dataSnapshot) {

        }

        @Override
        public void onChildMoved(DataSnapshot dataSnapshot, String s) {

        }

        @Override
        public void onCancelled(FirebaseError firebaseError) {

        }
    });
    semaphore.acquire();
    return temp;
}
Community
  • 1
  • 1
Sathindu
  • 407
  • 1
  • 5
  • 21
  • Waiting for an asynchronous operation is a waste of a thread. But if you insist: my answer here will show you both options: http://stackoverflow.com/questions/33203379/setting-singleton-property-value-in-firebase-listener – Frank van Puffelen Feb 26 '16 at 09:44
  • Sir, I read your post and tried in your way. But that didn't help me. Program didn't process after calling this method. any suggestions..? – Sathindu Feb 26 '16 at 12:03
  • I'm pretty sure the code I wrote works. But the good news for you is that you can always take the red pill mentioned in that answer. It's the better approach anyway. – Frank van Puffelen Feb 26 '16 at 12:39
  • I quickly tested the semaphore approach again yesterday and it indeed completely blocks the app. I think I tested on Android when I first wrote it, but am not sure anymore. But as said: the approach with a callback is the recommended approach anyway. The modern internet is asynchronous, the sooner you embrace that fact, the sooner you can build apps that make use of it. – Frank van Puffelen Feb 27 '16 at 08:20
  • Thank you looking in to that again . Instead of using that I used the Otto Library. (http://square.github.io/otto/) It worked the way I wanted – Sathindu Feb 27 '16 at 08:34

2 Answers2

2
public class MainActivity extends AppCompatActivity{
public static Bus bus;

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);         
    bus = new Bus(ThreadEnforcer.MAIN);
    bus.register(this);

    //CALL TO LOAD DATA FROM FIREBASE
    loadData();
}

private void loadData(){
    DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference();
    mDatabase.child("my-data").addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            //CREATE YOUR OWN OBJECT USING RECEIVED DATA
            MyObject o = new MyObject();
            //CALL FOR METHOD nextMethod()
            bus.post(o);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            Log.d("Error", databaseError.toString());
        }
    });
}

@Subscribe
private void nextMethod(MyObject o){

}
}

This is a very basic example for a usage of otto - EventBus. From bus.post(o), you can call to relavant Subscribed method.

Sathindu
  • 407
  • 1
  • 5
  • 21
  • Thanks for your time but how will you know when all callbacks are finished? this code will fire event every time you get the callback for each node in your firebase location. I am looking for something I get notified when all the child node callbacks are rcvd. – Shivaraj Patil Jul 23 '16 at 19:51
1

Solved : I used Otto EventBus Library from http://square.github.io/otto/ and it worked for me

Sathindu
  • 407
  • 1
  • 5
  • 21