如果Firebase搜索成功,则通知用户

时间:2017-04-11 23:12:15

标签: java firebase javafx firebase-realtime-database

我正在编写一个程序的静态方法,我一直在努力浏览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!");
}

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

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

任何人都可以想出一个更好的方法来处理这个问题,以便我可以正确地告知他们用户是否已添加到白名单中,或者是否找不到用户?

2 个答案:

答案 0 :(得分:0)

Firebase数据库上的操作本质上是异步的,所以即使你以某种方式使上述代码工作,最终你会遇到更复杂的情况,其中大部分代码行正在进行同步而不是处理功能你的申请。这将导致难以维护的代码容易破解。

所以最简单的&#34;自然&#34;处理数据库请求的方法是在代码发生时处理代码中的每个事件。这意味着在调用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!");
                });
            }
        }
    });
}

答案 1 :(得分:0)

我没有足够的声誉,因此我无法直接在您的问题中发表评论。对不起。

Firebase实际上有自己的主题。在调用if后,Firebase会打开一个新线程(或者只使用其已经存在的独立线程),因此您的原始线程会立即继续到public class FirebaseHandler { // parameters private DatabaseReference databaseReference; // constructor public FirebaseHandler() { // you'll most probably need these for some actions databaseReference = FirebaseDatabase.getInstance().getReference(); } // interface public interface FirebaseInterface { void firebaseComplete(String serverStatus, String email); } // listener private FirebaseInterface listener; // set listener public void setListener(FirebaseInterface listener) { this.listener = listener; } /* getter for references, these will be useful to avoid calling the wrong place */ // -- / public DatabaseReference getRoot() { return databaseReference; } // -- /email /* specify the data structure here */ public DatabaseReference getEmailRef() { return getRoot().child("email"); } // finally your method public static void addUser() { // your codes here... whiteRef.child(uid).setValue(email, new DatabaseReference.CompletionListener() { @Override public void onComplete(DatabaseError dbe, DatabaseReference dbr) { // some action here.... if (listener != null) listener.firebaseComplete("OK", email); } }); } } 块,因为它认为要完成操作,这就是你看到了结果。

因此,您需要的实际上是一个监听器,一旦Firebase完成其操作,它将与您的主要活动进行通信。既然你说你没有使用android,你可以创建一个特定的类来处理Firebase,它还包括接口和监听器。例如,

class Main implements FirebaseHandler.FirebaseInterface {

    FirebaseHandler firebaseHandler = new FirebaseHandler();
    firebaseHandler.setListener(this);
    firebaseHandler.addUser();

    @Override
    public void firebaseComplete(String serverStatus, String email) {
        firebaseHandler.setListener(null);      // optional to remove listener
        if (serverStatus.equals("OK") {
            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!"); 
        }
    }
}

您只需在活动中附加侦听器并实现其方法即可。所以在你的UI线程......

UPDATE  o
SET     sku = p.AutoSKU
FROM    o (NOLOCK)
        JOIN a (NOLOCK) ON a.Sku = o.sku
        JOIN p (NOLOCK) ON p.Code = a.ProductCode
WHERE   o.sku <> p.AutoSKU
        AND sku = a.Sku