为什么在添加值时未触发这些ValueEventListeners?

时间:2018-08-31 08:26:51

标签: android firebase firebase-realtime-database event-listener

代码如下:

final DatabaseReference TuidRef = usersRef.child(td);
        final DatabaseReference msgRef = TuidRef.child("rec_msg");
        final DatabaseReference FuidRef = TuidRef.child("fromUID");
        final DatabaseReference secretRef = TuidRef.child("rec_secret");


        msgRef.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot1) {
                ms = dataSnapshot1.getValue(String.class);
                flag++;

            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });

        FuidRef.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot2) {
                fUid = dataSnapshot2.getValue(String.class);
                flag++;
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });

        secretRef.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot3) {
                st = dataSnapshot3.getValue(String.class);
                flag++;

            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });

        String flagS = "" + flag;
        Log.i("flag",flagS);
        if(flag > 2)
            displayMessage();

我使用该标志知道ValueEventListeners被触发了多少次,但是在日志中发现该标志为0。

td是接收消息的人的uid。在下面的图片中,它与其他同级Childs的父键相同。

没有消息时,数据库看起来像这样: image1

当收到消息时,数据库如下所示: image2

编辑:当所有三个侦听器一次触发后,如何执行功能displayMessage()

不过,该值会同时添加到firebase数据库中的所有这三个对象中。

1 个答案:

答案 0 :(得分:0)

您将永远不会知道ValueEventListeners会被触发多少次,因为flag的值将始终保持0。发生这种情况是由于onDataChange()方法的异步行为,甚至在您尝试从数据库中获取数据之前就已经调用了该方法。真正发生的是,您正在尝试从数据库中获取数据,并在flag变量的初始值为0时立即尝试记录该数据。然后,当从数据库中获取数据完成时,它会更改标志的值,但不会再读取了。

对此问题的快速解决方案是在每个回调内部添加三个不同的标志,然后尝试分别在onDataChange()方法内部分别进行日志记录,如下所示:

msgRef.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot1) {
        ms = dataSnapshot1.getValue(String.class);
        flag1++;
        Log.i("flag1", String.valueOf(flag1));
    }

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {}
});

FuidRef.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot2) {
        fUid = dataSnapshot2.getValue(String.class);
        flag2++;
        Log.i("flag2", String.valueOf(flag2));
    }

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {}
});

secretRef.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot3) {
        st = dataSnapshot3.getValue(String.class);
        flag3++;
        Log.i("flag3", String.valueOf(flag3));
    }

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {}
});

如果您需要在代码中使用onDataChange()方法之外的位置来获取该标志的值,我建议您从此 post 中查看anwser的最后一部分我已经解释了如何使用自定义回调来完成。您也可以查看此 video 以获得更好的理解。

编辑:

msgRef.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot1) {
        ms = dataSnapshot1.getValue(String.class);
        flag++;

        FuidRef.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot2) {
                fUid = dataSnapshot2.getValue(String.class);
                flag++;

                secretRef.addValueEventListener(new ValueEventListener() {
                    @Override
                    public void onDataChange(@NonNull DataSnapshot dataSnapshot3) {
                        st = dataSnapshot3.getValue(String.class);
                        flag++;
                        Log.i("flag", String.valueOf(flag));
                    }

                    @Override
                    public void onCancelled(@NonNull DatabaseError databaseError) {}
                });
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {}
        });
    }

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {}
});