如何创建此Firebase查询以仅在特定的按键时间后返回项目

时间:2016-11-25 10:41:33

标签: android firebase firebase-realtime-database

跟进3.2. The annotated entity Java class问题回答我使用ValueEventListener仅使用此查询收听新项目:

Query query = ref.child(USER)  
                    .child(mFireBaseAuth.getCurrentUser().getUid())
                    .child(TOYS)
                    .orderByKey().startAt(-KXN04BDYdEG0aii9mMY);

query.addValueEventListener(mvalueEventListener);

上面代码示例中的-KXN04BDYdEG0aii9mMY是我已经拥有的最新项目,我希望在该时间戳之后只获得推送键。使用此代码,我还会再次获得-KXN04BDYdEG0aii9mMY,但这不是必需的,因为我已经拥有了它。

我该如何解决这个问题?也许为此Firebase推送键-KXN04BDYdEG0aii9mMY添加一毫秒?

TOYS键下方是Firebase Puch键列表

2 个答案:

答案 0 :(得分:1)

无法使用Firebase数据库查询指定独占锚点,因此您始终会获得为startAt()指定的密钥(以及指定endAt()时的密钥)。因此,您必须跳过客户端代码中的第一个/最后一个项目。

答案 1 :(得分:0)

我的工作就像我在问题中要求的那样。这是代码,因为它是我的答案,也是任何人的喜悦。

这是一个棘手的问题,我必须过滤掉我为startAt()指定的密钥,同时在'onDataChange()中处理第二个调用,因为TimeStamp在执行'时从Firebase进行了更正'。 ..ServerValue.TIMESTAMP);'

       // When startAt() get defined this will make sure that we dont save the 
       // startAt key item again.
       // Best would be if the startAfter("pushKey") existed but it does not.
       String skipStartAtKey = "";        


         /**
         * Typically when user sign in or app start
         */
        public void userSignedIn() {
            Log.i(TAG, "userSignedIn");
            // start listening
            activateFirebaseListeners();
        }

         /**
         * When user sign in this listeners are started
         */
        private void activateFirebaseListeners() {

           // [START Listen for history Address changes ]

            /**
             * The ChildEventListener.
             * This is only used when app first install or user wipe data
             */
            ChildEventListener userHistoryAddressChildEventListener = new ChildEventListener() {

                @Override
                public void onChildAdded(DataSnapshot snapshot, String prevKey) {
                    userHistoryAddressChildEvent(snapshot, prevKey);
                }

                @Override
                public void onChildChanged(DataSnapshot snapshot, String prevKey) {
                    userHistoryAddressChildEvent(snapshot, prevKey);
                }

                @Override
                public void onCancelled(DatabaseError error) {
                 // TODO dont forget to remove reset listeners
                }

                @Override
                public void onChildRemoved(DataSnapshot snapshot) {
                }

                @Override
                public void onChildMoved(DataSnapshot snapshot, String prevKey) {
                }
            };

            // If client don´t have any history start the ChildEventListener.
            // Typically this is the first time app starts or user have cleared data.
            if (ToyManager.getInstance().getHistoryItems(mFireBaseAuth.getCurrentUser().getUid()).size() == 0) {
                Log.i(TAG, "HistoryItems SIZE = 0 starting ChildEventListener");
                // Local cache of address history is empty get all address history for this user and start listen for new items
                final Query query = ref.child(USER_HISTORY).child(mFireBaseAuth.getCurrentUser()
                   .getUid())
                   .child(TOYS);
                mChildListenerMap.put(query.getRef(), userHistoryAddressChildEventListener);
                query.addChildEventListener(userHistoryAddressChildEventListener);

            } else {
                // If client have history then start the ValueEventListener.
                // Typically this is not the first time app starts.
                startListenForUserAddressHistory();
            }
            // [END Listen for history Address changes ]
        }

         private void userHistoryAddressChildEvent(DataSnapshot snapshot, String prevKey) {
            // get history for current user
            UserHistory.AddressHistory addressHistory = snapshot.getValue(UserHistory.AddressHistory.class);
            ToyManager.getInstance().addHistory(
                    mFireBaseAuth.getCurrentUser().getUid(),
                    addressHistory.getAddressId(),
                    addressHistory.getTime(),
                    addressHistory.getToy(),
                    addressHistory.getPushKey());
        }

     /**
         * Start listen for nye entries based on that server have entries<br>
         * and client have entries, typically this is not the first time App starts.
         * This uses a ValueEventListener.
         */
        private void startListenForUserAddressHistory() {
            // Local history is not empty so we must go get only new items
            final ValueEventListener listener = new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    // get history for current user
                    if (dataSnapshot.getChildrenCount() != 0) {
                        for (DataSnapshot child : dataSnapshot.getChildren()) {
                            UserHistory.AddressHistory addressHistory = child.getValue(UserHistory.AddressHistory.class);
                            if (dataSnapshot.getChildrenCount() == 1) {
                                // child count is one so this can be a SERVERTIME correctness call.
                                // skip the skipStartAtKey if key and time is the same.
                                if (addressHistory.getPushKey().equals(skipStartAtKey)) {
                                    // get historyItem
                                    HistoryItem historyItem = ToyManager.getInstance().getHistoryItem(mFireBaseAuth.getCurrentUser().getUid().concat(addressHistory.getPushKey()));
                                    // compare time
                                    if (historyItem.getTime().toString().equals(addressHistory.getTime().toString())) {
                                        Log.i(TAG, "time is the same exiting with return");
                                        return;
                                    } else
                                        Log.i(TAG, "time is different");
                                } else {
                                    Log.i(TAG, "PushKey not same as skipStartAtKey");
                                }

                            } else if (dataSnapshot.getChildrenCount() > 1) {
                                // two children or more so lets dump the skipStartAtKey and save the rest
                                Log.i(TAG, "TESTING  getChildrenCount > 1" + " skipStartAtKey " + skipStartAtKey + " time " + addressHistory.getTime());
                                if (addressHistory.getPushKey().equals(skipStartAtKey)) {
                                    Log.i(TAG, "PushKey same as skipStartAtKey");
                                    continue;
                                }
                            }
                            ToyManager.getInstance().addHistory(
                                    mFireBaseAuth.getCurrentUser().getUid(),
                                    addressHistory.getAddressId(),
                                    addressHistory.getTime(),
                                    addressHistory.getToy(),
                                    addressHistory.getPushKey());
                        }
                        ValueEventListener v = mValueListenerMap.get(dataSnapshot.getRef());
                        Log.i(TAG, "removing ValueEventListener for");
                        dataSnapshot.getRef().removeEventListener(v);
                        startListenForUserAddressHistory();
                    }
                }

                @Override
                public void onCancelled(DatabaseError databaseError) {
                    Log.w(TAG, "onCancelled" + databaseError.toException());
                     // TODO dont forget to remove reset listeners
                }
            };
            // get the latest history item
            HistoryItem historyItem = ToyManager.getInstance().orderHistoryByDateAndGetNewest(mFireBaseAuth.getCurrentUser().getUid());
            final Query query = ref.child(USER_HISTORY)
                    .child(mFireBaseAuth.getCurrentUser().getUid())
                    .child(TOYS)
                    .orderByKey().startAt(historyItem.getPushKey()); // start listen on the latest history
            mValueListenerMap.put(query.getRef(), listener);
            skipStartAtKey = historyItem.getPushKey();
            query.addValueEventListener(listener);
        }


         /**
         * App is closing or User has signed out
         * Called from both onClose() and userSignedOut()
         */
        private void closeFirebase() {
            userLogger.log(USER_SIGNED_OUT);

            // Close ChildEventListener(s)
            for (Map.Entry<DatabaseReference, ChildEventListener> entry : mChildListenerMap.entrySet()) {
                DatabaseReference ref = entry.getKey();
                ChildEventListener listener = entry.getValue();
                if (listener != null && ref != null)
                    ref.removeEventListener(listener);
            }
            // Close ValueEventListener(s)
            for (Map.Entry<DatabaseReference, ValueEventListener> entry : mValueListenerMap.entrySet()) {
                DatabaseReference ref = entry.getKey();
                ValueEventListener listener = entry.getValue();
                if (listener != null && ref != null)
                    ref.removeEventListener(listener);
            }
            // Close
            if (userValueEventListener != null)
                ref.child(USER).child(mFireBaseAuth.getCurrentUser().getUid())
                        .removeEventListener(userValueEventListener);
            if (userAuthListener != null)
                mFireBaseAuth.removeAuthStateListener(userAuthListener);
            userLogger = null;


            }