[英]Whenever the data is changed, both if and else statements are executed
我写了一个 function 来检查房间是否已满,如果是,则启动 toast,否则将播放器添加到房间。
当房间已满或有多个空闲位置时,一切正常,但当只有一个空闲位置时,if 和 else 语句都会执行。
发生这种情况是因为当玩家加入房间时数据发生了变化,我知道我必须使用 onDataChange 或 Transaction 来防止这种情况。
据我所知,我只能在直接访问数据库时使用它们,但是,我不想使用 function 直接访问数据库,而是使用我的 DAL class。
public void joinRoom(String category, String roomID, String roomName, Context context) {
// Checks if there is room for another player
roomDAL.isTheRoomFull(category, roomID, roomName, (isFull) -> {
Log.d("TAG", "isFull: " + isFull);
if (isFull) {
Toast.makeText(context, "The room is full", Toast.LENGTH_SHORT).show();
}
else{
// run only if the user confirmed the message
Runnable runIfConfirmed = new Runnable() {
@Override
public void run() {
// adds the player to the room
RoomDAL.addNewUser(category, roomID, playerDAL.getPlayerID());
// switches activity to GameRoom
SwitchActivities.GameRoom(context, roomName, category, roomID);
// updates the player's rooms list
playerDAL.addRoom(category, roomID);
Log.d("TAG", "Joined");
}
};
// ask the user to confirm that he wants to join the room
doubleCheck(category, roomID, roomName, runIfConfirmed);
}
});
return;
}
编辑:添加访问 Firebase 的相关类。
function 检查给定房间是否已满。
public static void isTheRoomFull(String category, String roomID, String nameRoom, OnSuccessListener<Boolean> listener) {
DatabaseReference database = getPathReference("Rooms/" + category + "/" + roomID);
database.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
// get the room object
RoomDAL.getRoom(roomID, category, (room) -> {
// Checks if the room has reached its limit
if (room.getNumOfPlayers() == room.getCapacity()) {
listener.onSuccess(true);
} else {
listener.onSuccess(false);
}
});
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
}
});
return;
}
function 将给定用户添加到给定房间
public static void addNewUser(String category, String roomID, String playerID) {
DatabaseReference reference = getPathReference("Rooms/" + category + "/" + roomID);
// Access the player's details in the FireStore Database
DocumentReference docRef = fStore.collection("users").document(playerID);
docRef.get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
@Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
Player p = documentSnapshot.toObject(Player.class);
String playerName = p.getFullName();
// Add the player to the usersList
DatabaseReference usersList = reference.child("usersList");
HashMap<String, Object> newUser = new HashMap<>();
newUser.put(playerID, playerName);
usersList.updateChildren(newUser);
}
});
// Increment the number of players in room
reference.runTransaction(new Transaction.Handler() {
@Override
public Transaction.Result doTransaction(MutableData mutableData) {
Room room = mutableData.getValue(Room.class);
if (room == null) {
return Transaction.success(mutableData);
}
// Update number of players
room.setNumOfPlayers(room.getNumOfPlayers() + 1);
// Set value and report transaction success
mutableData.setValue(room);
return Transaction.success(mutableData);
}
@Override
public void onComplete(DatabaseError databaseError, boolean committed,
DataSnapshot currentData) {
// Transaction completed
}
});
}
function 将给定房间添加到数据库中 userRooms 表中的用户房间列表中
public static void addRoom(String category, String roomKey) {
final FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference();
DatabaseReference usersRef = ref.child("userRooms/" + getPlayerID() + "/" + category);
Map<String, Object> groups = new HashMap<>();
groups.put(roomKey, roomKey);
usersRef.updateChildren(groups);
}
问题在这里:
public static void isTheRoomFull(String category, String roomID, String nameRoom, OnSuccessListener<Boolean> listener) {
DatabaseReference database = getPathReference("Rooms/" + category + "/" + roomID);
database.addValueEventListener(new ValueEventListener() {
...
由于您使用addValueEventListener
注册了侦听器,因此它是一个永久侦听器,既获取当前值,然后继续侦听对该值的更改。 因此,当您随后将用户添加到房间时,将再次调用值侦听器并为(现在已满)房间触发。
最简单的解决方法是使用单事件侦听器:
database.addListenerForSingleValueEvent(new ValueEventListener() {
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.