跟进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键列表
答案 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;
}