Wait Firebase Async Retrieve Data in Android

How to wait for Firebase Task to complete to get result as an await function

Data is loaded from Firebase asynchronously, since it may have to come from the server. While the data is being loaded, your main code continues to run. Then when the data is available, the task completes and your onSuccess gets called.

It's easiest to see what this means in practice by running in a debugger, or by adding some logging:

DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference();
Log.i("Firebase", "1. Starting to load data");
Task<DataSnapshot> dataSnapshotTask = mDatabase.get();
for (DataSnapshot parking: parkingsData) {
Log.i("Firebase", "2. Got data");
}
Log.i("Firebase", "3. After starting to load data");

When you run this code, it prints:

  1. Starting to load data

  2. After starting to load data

  3. Got data

This is probably not the order that you expected, but it actually working as intended. It also explains why you're not getting a result from your getParkingLots function: by the time your return parkings runs, the parkings.add(parking.getValue(Parking.class)) hasn't been called yet!


The solution for this is always the same: any code that needs the data from the database, needs to be inside your onSuccess method or be called from there. This means you can't return the parking lots from the function, but you can pass in a callback that takes them as a parameter. Or you could return a Task<HashMap<String, Parking>> pretty similar to what Firebase does got get().

For an example of the callback, see my longer explanation on: getContactsFromFirebase() method return an empty list

How to wait for the data to be fetched from Firebase Database

To solve this problem, please add the declaration of your receiverNames ArrayList inside the onDataChange() method, otherwise it will be null. This is happening due to asynchronous behaviour of that method. If you want to use those values outside that method, please see my answer from this post.

How to wait for firebase data fetch finishes and get values not a promise in react-native?

When you are attempting to get your firebase response you're not actually waiting for it. The code below does not wait for it to be executed.

getCustomersOnQeueu = async () => {
let customers = this.customersRef.orderByChild("ticket").once('value')
return customers
}

To WAIT for it to be executed use AWAIT:

getCustomersOnQeueu = async () => {
let customers = await this.customersRef.orderByChild("ticket").once('value')
return customers
}

Handle data returned by an Async task (Firebase)

What you are looking for is Callback interface, as for your needs you need simple interface that implement single method with single parameter, as there is no out of the box convention for Java 6 (Android Java version) you can easily create it by yourself:

interface Callback {

void act(List<AttendModel> models);
}

pass it as an argument to the firebase wrapping method, and call it with the result.

public void getAllAttendeesFor(String UUID, final ArrayList<AttendModel> attendArray, final Callback callback) {
final DatabaseReference attendObjects = getDatabaseTableWith(Constants.tableAttendObject);

Query queryRef = attendObjects.orderByChild(Constants.taAttendObjectUUID).equalTo(UUID);

queryRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {

for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
HashMap<String, Object> attend = (HashMap<String, Object>) postSnapshot.getValue();
String UUID = (String) attend.get(Constants.AttendObjectUUID);
String userUsername = (String) attend.get(Constants.AttendObjectUserUsername);

AttendModel attendModel = new AttendModel(userUsername, UUID);
attendArray.add(attendModel);

callback.act(attendArray)
}
}

@Override
public void onCancelled(DatabaseError databaseError) {

}
});

}

then in your upper level method:

public void getAttendants() {

ArrayList<AttendModel> attendees = new ArrayList<AttendModel>();
FirebaseConnection.getInstance().getAllAttendeesFor(uuid, attendees,
new Callable<List<AttendModel) {
void act(List<AttendModel> attendees){
//here you can update the UI
Log.d("attendees", String.valueOf(attendees.size()));
}
};


}

Just be aware that you can update the UI only if onDataChange method of the firebase query is called on the main thread.

Retrieve data synchronously from firestore database

Consider a scenario.

There is an 'n' no. of collections in your database root and you have their names in a list. You have to get the size() (No. of documents in it) of each of the collections. The only way to get this by synchronous calls is to wait until the pending request has been completed. You can achieve it like this:

 private void syncDocumentCounts() {
if (position > names.size() - 1) {
adapter.notifyDataSetChanged();
} else {
FirebaseFirestore.getInstance().collection(names.get(position)).get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
@Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
list.add(queryDocumentSnapshots.size());
position++;
syncDocumentCounts();
}
});
}
}

Here,

position = public int = 0

names = list of names of collections

list is the list in which we have to add the value.



Related Topics



Leave a reply



Submit