childSnapshot.getKey();正在检索所有密钥,而不仅仅是一个密钥(我选择的那个)

childSnapshot.getKey(); is retrieving all the key instead of just one (the one that I choose)

提问人:Katufo Prem 提问时间:11/17/2023 最后编辑:Frank van PuffelenKatufo Prem 更新时间:11/17/2023 访问量:58

问:

我正在努力从 RecyclerView 中仅提取所选项目的键,然后更新与该键关联的值或节点。当 reservationName 不同时,当前实现会正常运行,例如在“Wedding”的情况下。但是,当该 reservationName 中有多个密钥或预留项时,它会遇到问题。具体而言,如果我尝试设置或取消预订(洗礼),则该操作会影响所有预订(洗礼)或钥匙的状态,而不仅仅是我从列表项中选择的预订或密钥的状态。

RecyclerView 列表示例。我有一个用于重新安排的日期选择器,即使我选择了第一个,它也会显示两个日期选择器。首先,第一个日期选择器将更新第二个日期,然后第二个日期选择器将更新第一个日期选择器。取消、付款、重新安排或设置状态等所有功能都是一样的:

enter image description here

这是我的火力库结构:

enter image description here

我用于在预留中工作的示例代码。我使用Toast来检索密钥,然后它显示所有密钥:

private void cancelReservation(Reservation reservation) {
    DatabaseReference reservationRef = reservationsRef.child(reservation.getName());

    reservationRef.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            if (dataSnapshot.exists()) {
                for (DataSnapshot childSnapshot : dataSnapshot.getChildren()) {
                    String key = childSnapshot.getKey();
                    if (childSnapshot.hasChild("status")) {
                        String status = childSnapshot.child("status").getValue(String.class);

                        if (status != null) {
                            //set status to "Cancelled"
                            //alert dialog
                            AlertDialog.Builder builder = new AlertDialog.Builder(ListofReserve.this);
                            builder.setTitle("Cancel Reservation");
                            builder.setMessage("Are you sure you want to cancel this reservation?");
                            builder.setPositiveButton("Yes", (dialog, which) -> {
                             if (status.equals("Cancelled")) {
                                 Toast.makeText(ListofReserve.this, "Reservation already cancelled", Toast.LENGTH_SHORT).show();
                             } else {
                                 DatabaseReference specificReservationRef = reservationsRef
                                         .child(reservation.getName())
                                         .child(key);

                                 specificReservationRef.child("status").setValue("Cancelled")
                                         .addOnCompleteListener(task -> {
                                             if (task.isSuccessful()) {
                                                 Toast.makeText(ListofReserve.this, "Reservation Cancelled", Toast.LENGTH_SHORT).show();
                                             } else {
                                                 Toast.makeText(ListofReserve.this, "Failed to cancel reservation", Toast.LENGTH_SHORT).show();
                                             }
                                         });
                             }
                            });
                            builder.setNegativeButton("No", (dialog, which) -> {
                                Toast.makeText(ListofReserve.this, " " + key, Toast.LENGTH_SHORT).show();
                            });
                            builder.create().show();
                        } else {
                            Toast.makeText(ListofReserve.this, "Status not available", Toast.LENGTH_SHORT).show();
                        }
                    } else {
                    }
                }
            } else {
                Toast.makeText(ListofReserve.this, "Reservation not found", Toast.LENGTH_SHORT).show();
            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            Toast.makeText(ListofReserve.this, "Error fetching data: " + databaseError.getMessage(), Toast.LENGTH_SHORT).show();
        }
    });
}

您可能需要实现 RecyclerView:

private class ReservationAdapter extends RecyclerView.Adapter<ReservationAdapter.ReservationViewHolder> {

    private List<Reservation> reservations;
    private ActivityResultLauncher<Intent> activityResultLauncher;

    public ReservationAdapter(List<Reservation> reservations, ActivityResultLauncher<Intent> activityResultLauncher) {
        this.reservations = reservations;
        this.activityResultLauncher = activityResultLauncher;
    }


    @NonNull
    @Override
    public ReservationViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.reservation_item, parent, false);
        return new ReservationViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ReservationViewHolder holder, int position) {
        Reservation reservation = reservations.get(position);
        holder.reservationName.setText(reservation.getName());
        holder.reservationStatus.setText("Status: " + reservation.getStatus());
        holder.reservationDate.setText("Date of Reservation: " + reservation.getDate());

        holder.itemView.setOnClickListener(v -> {
            //show a dialog with options to cancel or reschedule
            showReservationOptionsDialog(reservation);
        });
    }
java android firebase firebase-realtime-database

评论

1赞 Alex Mamo 11/17/2023
如果只需要一个节点,为什么还要遍历所有结果?你能解释一下你想得到的确切节点是什么吗?
0赞 Katufo Prem 11/18/2023
我很欣赏你的评论。例如,有 5 个预留名称;洗礼、婚礼、圣餐、确认和安魂曲。在回收商名单中,有 2 个洗礼和 1 个婚礼。
0赞 Katufo Prem 11/18/2023
如果我想用 A 洗礼改变一些东西,它也会影响另一个 B 洗礼,而不仅仅是更新 A 洗礼。
1赞 Alex Mamo 11/18/2023
那么,为什么不创建一个仅指向并进行更改的引用呢?A Baptism
1赞 Alex Mamo 11/18/2023
为什么你说你不能检索密钥,有一种方法可以做到这一点。您是否尝试过使用DataSnapshot#getKey()

答:

1赞 Rob 11/17/2023 #1

您正在获取名称为“Baptims”的预留的所有子项并更改每个状态,您应该仅通过名称或 ID 更改该子项的状态来获取确切的子项。像这样的东西

    private void cancelReservation(Reservation reservation) {
        DatabaseReference reservationRef = reservationsRef.child(reservation.getName());

        reservationRef.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                if (dataSnapshot.exists()) {
                   DataSnapshot childSnapshot = dataSnapshot.getChild(reserveation.id) // somehow get the exact child, can't write exact code as do not know how your object are constructed
     
    String key = childSnapshot.getKey();
                        if (childSnapshot.hasChild("status")) {
                            String status = childSnapshot.child("status").getValue(String.class);

                            if (status != null) {
                                //set status to "Cancelled"
                                //alert dialog
                                AlertDialog.Builder builder = new AlertDialog.Builder(ListofReserve.this);
                                builder.setTitle("Cancel Reservation");
                                builder.setMessage("Are you sure you want to cancel this reservation?");
                                builder.setPositiveButton("Yes", (dialog, which) -> {
                                 if (status.equals("Cancelled")) {
                                     Toast.makeText(ListofReserve.this, "Reservation already cancelled", Toast.LENGTH_SHORT).show();
                                 } else {
                                     DatabaseReference specificReservationRef = reservationsRef
                                             .child(reservation.getName())
                                             .child(key);

                                     specificReservationRef.child("status").setValue("Cancelled")
                                             .addOnCompleteListener(task -> {
                                                 if (task.isSuccessful()) {
                                                     Toast.makeText(ListofReserve.this, "Reservation Cancelled", Toast.LENGTH_SHORT).show();
                                                 } else {
                                                     Toast.makeText(ListofReserve.this, "Failed to cancel reservation", Toast.LENGTH_SHORT).show();
                                                 }
                                             });
                                 }
                                });
                                builder.setNegativeButton("No", (dialog, which) -> {
                                    Toast.makeText(ListofReserve.this, " " + key, Toast.LENGTH_SHORT).show();
                                });
                                builder.create().show();
                            } else {
                                Toast.makeText(ListofReserve.this, "Status not available", Toast.LENGTH_SHORT).show();
                            }
                        } else {
                        }
                } else {
                    Toast.makeText(ListofReserve.this, "Reservation not found", Toast.LENGTH_SHORT).show();
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
                Toast.makeText(ListofReserve.this, "Error fetching data: " + databaseError.getMessage(), Toast.LENGTH_SHORT).show();
            }
        });
    }

评论

0赞 Katufo Prem 11/18/2023
谢谢你的评论。我稍后会尝试这个,并会更新你。我还可以在我的代码中为您提供节点的结构。
1赞 Rob 11/19/2023
你试过吗?它有效吗?@KatufoPrem
0赞 Katufo Prem 11/23/2023
有点是的,但是您帮助我删除了不必要的行,例如“for (DataSnapshot childSnapshot : dataSnapshot.getChildren()) {”,它检索所有保留中的所有键。就像您的代码一样,我设法通过添加 'dataSnapshot.child(reservation.getKey());谢谢。很感激!