首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Firebase (GeoFire)两次保存数据

Firebase (GeoFire)两次保存数据
EN

Stack Overflow用户
提问于 2018-01-12 11:24:12
回答 2查看 300关注 0票数 0

我试图在Firebase中使用GeoLocations保存GeoFireGeoLocation的键必须是服务器时间戳。因此,数据模型如下:

代码语言:javascript
复制
{
  "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()保存了两次键(时间戳),并以毫秒和秒为单位进行了小的更改。

为什么会发生这种事?

代码语言:javascript
复制
//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) {

                    }
                });
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-01-12 12:39:39

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

代码语言:javascript
复制
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
EN

Stack Overflow用户

发布于 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行中,如下所示:

代码语言:javascript
复制
    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) {

                }
            });
}

});

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48225292

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档