【问题标题】:Dealing with Asynchronous Listeners in Firebase to Retrieve Data在 Firebase 中处理异步侦听器以检索数据
【发布时间】:2017-03-02 07:41:10
【问题描述】:

我正在学习使用 Firebase,想知道我是否做得对。如果我理解正确,您只能使用 Firebase 中的侦听器异步检索数据。我将尝试用一个例子来解释我的问题。假设我有一个简单的聊天应用程序的以下数据库数据:

chat_info:
  chatID_1:
    participants:
      uId_1: true
      uId_2: true

users:
  uId_1:
    display_name: "David"
    participated_chats:
      chatID_1: true
      chatID_2: true
  uId_2:
    display_name: "Jason"
    participated_chats:
      chatID_1: true
      chatID_2: true

现在,我正在尝试列出 David 参与的聊天。所以我执行以下操作:

    ArrayList<String> chatIdList = new ArrayList<String>();
    // Retrieve chat Ids of participating chats
    usersRef.child(mFirebaseUser.getUid()).child("participated_chats").addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            chatIdList.clear();

            // Save each chat Id to an arraylist
            for (DataSnapshot child : dataSnapshot.getChildren()) {
                chatIdList.add(child.getKey());

                // when loop hits the last user of the dataSnapsot
                if(chatIdList.size() >= dataSnapshot.getChildrenCount()) {

                    // For each chat Id, retrieve participants' uIds
                    for(String chatId : chatIdList) {
                        chatInfoRef.child(chatId).addListenerForSingleValueEvent(new ValueEventListener() {
                            @Override
                            public void onDataChange(DataSnapshot dataSnapshot) {
                                Chat chat = dataSnapshot.getValue(Chat.class);  // In a Chat class, there is public Map<String, Boolean> participants = new HashMap<>();
                                chatDetailList.add(chat);
                                chatListAdapter.notifyDataSetChanged();
                            }
                            @Override
                            public void onCancelled(DatabaseError databaseError) {}
                        });

                    }
                }
            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

现在,对于用户参与的每个聊天,我都有参与者的 uId。但是,由于我想显示用户名,而不是 uId,我必须再次从另一个节点检索数据。这是我的担心,因为我必须添加另一个异步侦听器来从不同的节点检索数据。如果它是 MySQL 之类的东西,那不会有问题,但 Firebase 监听器是异步的。这种异步侦听器检索数据的想法非常令人困惑,并且想知道我是否做得对。我应该在这里做什么?

【问题讨论】:

  • 乍一看这看起来不错:您正在客户端上循环以“加入”数据库中的用户数据。有什么问题?
  • 当我使用异步侦听器循环用户数据时,是否保证按顺序返回值?换句话说,当第一个侦听器运行时,第二个侦听器会立即运行,无论第一个侦听器是否返回值,因为它的任务是异步的。所以我想知道是否多个侦听器是异步运行的,是否有可能将返回的值无序地添加到数组列表中?
  • 所有到数据库的流量都通过同一个套接字,所以它们都是按顺序执行的。请参阅 this answer 以了解有关流水线的更多信息。
  • 这回答了我的问题!非常感谢弗兰克 :)

标签: android firebase firebase-realtime-database


【解决方案1】:

您可以将第一个侦听器附加到/users/uId_1 以获取整个用户对象,然后您可以简单地从 dataSnapshot 值中获取用户的用户名/显示名称。

这是一个例子。

ArrayList<String> chatIdList = new ArrayList<String>();
// Retrieve chat Ids of participating chats
usersRef.child(mFirebaseUser.getUid()).addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        chatIdList.clear();

        User user = dataSnapshot.getValue(User.class);
        String username = user.getDisplay_name();

        Map<String, Boolean> participated_chats = user.getParticipated_chats();
        // Save each chat Id to an arraylist
        for (Map.Entry<String, Boolean> child : participated_chats.entries()) {
            chatIdList.add(child.getKey());

            // ... continues
        }
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {

    }
});

【讨论】:

    猜你喜欢
    • 2017-06-03
    • 1970-01-01
    • 2017-01-11
    • 1970-01-01
    • 1970-01-01
    • 2016-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多