有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java通知用户Firebase搜索是否成功

我正在为一个我一直在开发的程序编写一个静态方法,以检查Firebase数据库中“灰色列表”中的条目,并对照用户输入检查该条目是否存在。我能够很好地找到条目,但由于在Firebase中读取/写入数据时线程工作方式的一些限制,我无法确定如何通知用户操作是否成功

我有以下方法:

public static void addUser() {
    final boolean [] complete = new boolean[1];
    final String email = Tools.getEmail();
    DatabaseReference grayRef = FirebaseDatabase.getInstance().getReference().child("graylist");

    // Search the graylist for the email specified.
    CountDownLatch latch = new CountDownLatch(1); // need this so Parse-Ly doesn't close before event fires
    grayRef.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onCancelled(DatabaseError dbe) {}

        @Override
        public void onDataChange(DataSnapshot snap) {
            Iterable<DataSnapshot> graylist = snap.getChildren();
            for(DataSnapshot gray : graylist) {
                String uid = gray.getKey();
                String em = gray.getValue(String.class);
                if(em.equals(email)) {
                    // We found the one we're looking for. Insert its UID into the whitelist.
                    DatabaseReference whiteRef = FirebaseDatabase.getInstance().getReference().child("whitelist");
                    whiteRef.child(uid).setValue(email, new DatabaseReference.CompletionListener() {
                        @Override
                        public void onComplete(DatabaseError dbe, DatabaseReference dbr) {
                            complete[0] = true;
                            latch.countDown();
                            if(dbe != null) {
                                System.err.println("Error adding user to whitelist!");
                                dbe.toException().printStackTrace();
                            }
                        }
                    });
                    break;
                }
            }
            if(latch.getCount() > 0) {
                complete[0] = false;
                latch.countDown();
            }
        }
    });

    try {
        latch.await(); // wait for event to fire before we move on
    } catch(InterruptedException ie) {
        System.err.println("ERROR: Add user latch interrupted!");
        ie.printStackTrace();
    }

    if(complete[0]) ParselyMain.createAlert(AlertType.CONFIRMATION, "User Added", "User added to the whitelist!");
    else ParselyMain.createAlert(AlertType.INFORMATION, "User Not Found", "That user was not found in the graylist!");
}

我意识到最终的布尔数组有多粗糙,但即使这样也不适合我。其想法是使用倒计时锁存器,只有在写入成功时才倒计时。如果读取了灰色列表中的所有条目,并且CountDownLatch仍为1,则未写入任何内容,并且应该倒计时以退出线程,但布尔值将确定操作是否成功

问题是,在调用onComplete方法之前,它似乎在我的for循环之后到达if块,导致它认为操作失败(尽管我在Firebase上的数据库显示不是这样),并输出错误的警报

有没有人能想出更好的方法来处理这个问题,这样我就可以在用户被添加到白名单或者没有找到用户时正确地通知他们


共 (1) 个答案

  1. # 1 楼答案

    Firebase数据库上的操作本质上是异步的,因此,即使您以某种方式使上述代码正常工作,最终也会遇到更复杂的情况,其中许多代码行正在进行同步,而不是处理应用程序的功能。这将导致不可维护的代码很容易被破坏

    因此,处理数据库请求的最简单且“自然”的方法是在代码中的每个事件发生时处理它。这意味着在调用onComplete方法时通知用户更新成功,在检查所有子实体且未找到匹配项时通知用户更新失败:

    public static void addUser() {
        final String email = Tools.getEmail();
        DatabaseReference grayRef = FirebaseDatabase.getInstance().getReference().child("graylist");
    
        // Search the graylist for the email specified.
        grayRef.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onCancelled(DatabaseError dbe) {}
    
            @Override
            public void onDataChange(DataSnapshot snap) {
                boolean found = false;
                Iterable<DataSnapshot> graylist = snap.getChildren();
                for(DataSnapshot gray : graylist) {
                    String uid = gray.getKey();
                    String em = gray.getValue(String.class);
                    if(em.equals(email)) {
                        found = true;
                        // We found the one we're looking for. Insert its UID into the whitelist.
                        DatabaseReference whiteRef = FirebaseDatabase.getInstance().getReference().child("whitelist");
                        whiteRef.child(uid).setValue(email, new DatabaseReference.CompletionListener() {
                            @Override
                            public void onComplete(DatabaseError dbe, DatabaseReference dbr) {
                                complete[0] = true;
                                if(dbe != null) {
                                    System.err.println("Error adding user to whitelist!");
                                    dbe.toException().printStackTrace();
                                } else {
                                    Platform.runLater(() -> {                                  
                                        ParselyMain.createAlert(AlertType.CONFIRMATION, "User Added", "User added to the whitelist!");
                                    });
                                }
                            }
                        });
                        break;
                    }
                }
                if(!found) {
                    Platform.runLater(() -> {
                        ParselyMain.createAlert(AlertType.INFORMATION, "User Not Found", "That user was not found in the graylist!");
                    });
                }
            }
        });
    }