我试图在Firebase中使用GeoLocations保存GeoFire,GeoLocation的键必须是服务器时间戳。因此,数据模型如下:
{
"geofire" : {
"1515755844766" : {
".priority" : "ez53wur36x",
"g" : "ez53wur36x",
"l" : [ 39.66227391798104, -6.372992321848869 ]
},
"1515755844962" : {
".priority" : "ez53wur36x",
"g" : "ez53wur36x",
"l" : [ 39.66227391798104, -6.372992321848869 ]
},
"1515755851938" : {
".priority" : "s6xhjeruen",
"g" : "s6xhjeruen",
"l" : [ 14.78428771229891, 21.346221640706066 ]
},
"1515755852148" : {
".priority" : "s6xhjeruen",
"g" : "s6xhjeruen",
"l" : [ 14.78428771229891, 21.346221640706066 ]
}
},
"serverTime" : 1515755852148
}我只执行了两次下面的代码来获得这些值(四个值),因此它为每个.setLocation()保存了两次键(时间戳),并以毫秒和秒为单位进行了小的更改。
为什么会发生这种事?
//Get reference to Firebase DB
dbRef = FirebaseDatabase.getInstance().getReference();
// Get reference to Geofire inside FIrebaseDB
dbRefGeofire = FirebaseDatabase.getInstance().getReference("geofire");
geoFire = new GeoFire(dbRefGeofire);
dbRef.child("serverTime").setValue(ServerValue.TIMESTAMP); //Executes TIMESTAMP function in firebase server and stores that value
dbRef.child("serverTime").addValueEventListener(new ValueEventListener() { //Gets TIMESTAMP value from the server
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
serverTime = String.valueOf(dataSnapshot.getValue());
geoFire.setLocation(serverTime, new GeoLocation(latLng.latitude,latLng.longitude), new GeoFire.CompletionListener() {
@Override //Save geolocation with timestamp in seconds
public void onComplete(String key, DatabaseError error) {
if (error != null) {
Log.v("Informe","There was an error saving the location to GeoFire: " + error);
} else {
Log.v("Informe","Location saved on server successfully!");
}
}
});
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});发布于 2018-01-12 12:39:39
要解决这个问题,请使用以下代码:
ValueEventListener eventListener = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
String serverTime = String.valueOf(dataSnapshot.getValue(Long.class));
geoFire.setLocation(serverTime, new GeoLocation(latLng.latitude,latLng.longitude), new GeoFire.CompletionListener() {
@Override
public void onComplete(String key, DatabaseError error) {
if (error != null) {
Log.v("Informe","There was an error saving the location to GeoFire: " + error);
} else {
Log.v("Informe","Location saved on server successfully!");
}
}
});
}
@Override
public void onCancelled(DatabaseError databaseError) {}
};
dbRef.child("serverTime").addListenerForSingleValueEvent(eventListener);addListenerForSingleValueEvent解决了你的问题。
发布于 2018-01-12 11:45:01
ValueEventListener执行了两次,如果在serverTime = String.valueOf(dataSnapshot.getValue());设置断点,您将清楚地看到它,
,为什么会这样?
因为您的dbRef.child("serverTime").setValue(ServerValue.TIMESTAMP);是异步的,所以应用程序继续运行并设置一个新的valueEventListener,
,它将立即调用,而不需要dataSnapshot中的任何数据。
然后,当您异步完成'setValue‘函数,'onDataChange’将再次调用(因为该值已被更改)
您可以添加“datasnapshout.isExist()”来解决这个问题,
或者将“onCompleteListener”添加到您的setValue行中,如下所示:
dbRef.setValue(ServerValue.TIMESTAMP, new DatabaseReference.CompletionListener() {
@Override
public void onComplete(DatabaseError databaseError, DatabaseReference dataRef) {
dbRef.child("serverTime").addValueEventListener(new ValueEventListener() { //Gets TIMESTAMP value from the server
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
serverTime = String.valueOf(dataSnapshot.getValue());
geoFire.setLocation(serverTime, new GeoLocation(latLng.latitude,latLng.longitude), new GeoFire.CompletionListener() {
@Override //Save geolocation with timestamp in seconds
public void onComplete(String key, DatabaseError error) {
if (error != null) {
Log.v("Informe","There was an error saving the location to GeoFire: " + error);
} else {
Log.v("Informe","Location saved on server successfully!");
}
}
});
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}});
https://stackoverflow.com/questions/48225292
复制相似问题