Firebase(GeoFire)两次保存数据

时间:2018-01-12 11:24:12

标签: android firebase firebase-realtime-database geofire

我尝试将GeoLocationsGeoFire保存在Firebase中,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) {

                    }
                });

2 个答案:

答案 0 :(得分:1)

要解决此问题,请使用以下代码:

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解决了您的问题。

答案 1 :(得分:0)

如果要在serverTime = String.valueOf(dataSnapshot.getValue());处设置断点,则ValueEventListener会执行两次 你会清楚地看到它,

为什么会这样?

因为您的dbRef.child("serverTime").setValue(ServerValue.TIMESTAMP);是异步的, 应用程序继续运行并设置一个新的valueEventListener,

将立即调用dataSnapshot

中没有任何数据

然后,当你的async'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) {

                }
            });
}

});