Wait Firebase async retrieve data in Android
Asked Answered
V

2

14

I need to store the result of FireBase getValue method that is async by his own. I can't use something like "onPostExecute()" and, for my purpose, i can't execute all my operation "into onDataChange()" because i need some references in future time in other activities.

Here my snippet to retrieve data:

    List<Village> villages = new LinkedList<>();
    Firebase ref = new Firebase("MYFIREBASEURL").child("village");
    ref.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot snapshot) {
            spinnerArray.clear();
            for (DataSnapshot postSnapshot : snapshot.getChildren()) {
                Village v = postSnapshot.getValue(Village.class);
                villages.add(v);
            }
        }

        @Override
        public void onCancelled(FirebaseError firebaseError) {
            System.out.println("The read failed: " + firebaseError.getMessage());
        }
    });

If i try to read villages out of "onDataChange" i have, naturally for his async life, null value. There is a way to ensure that onDataChange was called?.

Valorie answered 15/11, 2015 at 18:11 Comment(1)
You'll need to rephrase your needs into "whenever the data changes, I want to do ABC". Or you can wait for the data, it's possible just not generally recommended. See this Q&A for details/samples: #33203879Flunkey
B
23

You can define a listener interface to handle it. Example:

 public interface OnGetDataListener {
    public void onStart();
    public void onSuccess(DataSnapshot data);
    public void onFailed(DatabaseError databaseError);
}

And I create a custom function to get data in Database.class:

  public void mReadDataOnce(String child, final OnGetDataListener listener) {
    listener.onStart();
   FirebaseDatabase.getInstance().getReference().child(child).addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            listener.onSuccess(dataSnapshot);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            listener.onFailed(databaseError);
        }
    });
}

When I want to get data from Main.class, I do:

private void mCheckInforInServer(String child) {
    new Database().mReadDataOnce(child, new OnGetDataListener() {
        @Override
        public void onStart() {
            //DO SOME THING WHEN START GET DATA HERE
        }

        @Override
        public void onSuccess(DataSnapshot data) {
           //DO SOME THING WHEN GET DATA SUCCESS HERE
        }

        @Override
        public void onFailed(DatabaseError databaseError) {
           //DO SOME THING WHEN GET DATA FAILED HERE
        }
    });

}

By this way, you can reuse your method and handle data.

Blether answered 18/10, 2016 at 5:2 Comment(1)
This does not fix the problem. The asynchronous call goes through as usual, only retrieving the data after it is needed.Busk
B
2

Just to add to Manh's answer, one would call onStart() just before

 FirebaseDatabase.getInstance().getReference().child(child).addListenerForSingleValueEvent(new ValueEventListener() {

And in onStart(), typically you would show a progressDialog:

    if (mProgressDialog == null) {
        mProgressDialog = new ProgressDialog(getContext());
        mProgressDialog.setMessage(getString(R.string.loading));
        mProgressDialog.setIndeterminate(true);
    }

    mProgressDialog.show();

And in onSuccess() dismiss the dialog and load the data onto GUI (or whatever you want to do)

    if (mProgressDialog != null && mProgressDialog.isShowing()) {
        mProgressDialog.dismiss();
    }
Bioecology answered 7/6, 2017 at 13:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.