I having a problem with GeoFire and so, Firebase.
I want to update an information on the UI based on a GeoFire location trigger. When an action occur on client side, a data has to be saved on the Firebase database, and the GeoFire has to be update.
I'll be more clear with some code.
1- The Action on client side. Store a temperature for an user and its location.
public void sendTemperature(Float temp) {
LatLng myPosition = getMyPosition();
//instantiate the db connection
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference dbTemperatures = database.getReference("temperatures");
//push the value to global temperature db
String tempId = dbTemperatures.push().getKey();
dbTemperatures.child("/"+tempId).setValue(temp);
//create an index to link the user with its last sent temperature
DatabaseReference dbUserLastTemperature = database.getReference("users_last_temperature");
dbUserLastTemperature.child(userId).setValue(tempId);
//update the geofireDb (here is the problem)
geoUsersTemperatures.removeLocation(userId);
geoUsersTemperatures.setLocation(userId, new GeoLocation(myPosition.latitude, myPosition.longitude));
}
2 - The listeners on client side. Get notified of temperatures of users nearby.
GeoQuery usersTemperatureGeoQuery = geoUsersTemperatures.queryAtLocation(new GeoLocation(getMyPosition().latitude, getMyPosition().longitude), mapsRadius);
usersTemperatureGeoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
@Override
public void onKeyEntered(String key, GeoLocation location) {
System.out.println(String.format("Key %s entered the search area at [%f,%f]", key, location.latitude, location.longitude));
addTemperature(key, location);
}
@Override
public void onKeyExited(String key) {
System.out.println(String.format("Key %s is no longer in the search area", key));
removeTemperature(key);
}
@Override
public void onKeyMoved(String key, GeoLocation location) {
System.out.println(String.format("Key %s moved within the search area to [%f,%f]", key, location.latitude, location.longitude));
moveTemperature(key, location);
}
@Override
public void onGeoQueryReady() {
System.out.println("All initial data has been loaded and events have been fired!");
}
@Override
public void onGeoQueryError(DatabaseError error) {
System.err.println("There was an error with this query: " + error);
}
});
3- The problem. What I expected to happen is that, when a new temperature is sent, the listener detect its deletion and its new insertion (but actually its key isn't changing) , and so I can update my UI. This does not happens, as the two actions are so fast that the GeoFire listener doesn't trigger anything, as for it there is nothing changed in the db.
Is there a way to get the listener behave as I would like it to?
This can probably be solved by using a so-called completion listener in to removeLocation()
.
A quick, untested write-up (so it may contain syntax errors):
geoUsersTemperatures.removeLocation(userId, new GeoFire.CompletionListener {
public void onComplete(String key, DatabaseError error) {
geoUsersTemperatures.setLocation(userId, new GeoLocation(myPosition.latitude, myPosition.longitude));
});
});
With this approach you're waiting until the database acknowledges that it has removed the old location before setting a new location.