2016-10-20 56 views
0

我正在学习使用Firebase并希望知道我是否正确地进行了操作。如果我理解正确,则只能使用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 

现在,我想列出大卫参加了聊天记录,这样我像做了以下内容:

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) { 

     } 
    }); 

现在,我有参与者的用户参加每次聊天的uIds。但是,由于我想显示用户名,而不是uId,我必须再次从另一个节点检索数据。这是我的担心,因为我必须添加另一个异步列表器来从不同节点检索数据。如果它像MySQL一样,这不会成为问题,但Firebase侦听器是异步的。这种异步侦听器检索数据的想法非常混乱,并且奇怪我是否正确地做了这件事。我应该在这里做什么?

+0

乍一看,这看起来很好:你在客户端循环“加入”来自数据库的用户数据。有什么问题? –

+0

当我使用异步侦听器循环使用用户数据时,是否保证按顺序返回值?换句话说,当第一个侦听器运行时,第二个侦听器会立即运行,无论第一个侦听器是否因为其任务是异步而返回值。所以我想知道是否多个侦听器异步运行,是否有可能将返回值无序添加到数组列表? –

+1

所有到数据库的流量都在同一个套接字上,所以它们都按顺序执行。见[这个答案](http://stackoverflow.com/questions/35931526/speed-up-fetching-posts-for-my-social-network-app-by-using-query-instead-of-obse/35932786# 35932786)了解更多关于流水线的内容。 –

回答

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) { 

    } 
}); 
相关问题