2017-10-13 134 views
1

我正在开发一款Android应用程序,其中年长的孩子可以捡起年幼的孩子并步行上学。随着应用程序的认证(电子邮件和密码)年轻的孩子可以选择三个地址之间得到拾取。截至目前我的实时数据库是这样的:Android - 从Firebase中检索数据

enter image description here

我想要检索不同的地址,谁选择了地址的用户。我想我必须使用recyclerview来获取数据,但我不确定是否可以使用我的数据库结构。

enter image description here

+0

这听起来可行,但我肯定会建议看看FirebaseUI来帮助解决这个问题。它有特殊的适配器,例如'FirebaseRecyclerAdapter'。对于这个具体我看看:https://github.com/firebase/FirebaseUI-Android/blob/master/database/README.md#using-firebaseui-with-indexed-data –

+0

感谢您的答案,我看了在你提供的链接上,但我仍然怀疑如何查询节点。我如何从Adresses节点获取用户名? – JDoe

+0

@FrankvanPuffelen我希望你不介意我在这里跳过一个答案 - 我已经起草了之前发现你的评论! – Grimthorr

回答

1

继续从my previous answer,这一个应该符合您的要求,以创建一个所有地址及其关联用户的列表,这可能更接近你正在寻找的。

再次,您可以使用FirebaseUI database package来简化RecyclerView创建。

你需要启动非规范化的数据,所以你的数据结构也应包括地址,用户名节点:

{ 
    "Addresses" : { 
    "Street 10" : { 
     "name" : "Street 10", 
     "users" : { 
     "VAzdMWafK6cyhmJnOI4br5xiQg93" : "John" 
     } 
    } 
    }, 
    "User" : { 
    "VAzdMWafK6cyhmJnOI4br5xiQg93" : { 
     "username" : "John", 
     "address" : "Street 10" 
    } 
    } 
} 

注:您只需要用户ID添加到他们所选择的地址(和如果他们改变了选择,则删除该节点),所以不要使用"VAzdMWafK6cyhmJnOI4br5xiQg93" : false作为用户未选择的地址,因为这可能会导致混淆。

然后你可以使用:

Query query = FirebaseDatabase.getInstance().getReference("/Addresses"); 

FirebaseRecyclerOptions<Address> options = new FirebaseRecyclerOptions.Builder<Address>() 
     .setQuery(query, Address.class) 
     .build(); 

哪里Address是一样的东西:

public class Address { 
    private String name; 
    private Map<String, String> users; 

    public Address() {} 

    public Map<String, String> getUsers() { 
     return this.users; 
    } 

    // ... 
} 

而且create a FirebaseRecyclerAdapter instanceoptions变量。然后,在绑定适配器中的视图时,您可以访问users映射以列出选择此地址的每个用户,而无需不必要地加载整个User对象。

这种模式被称为denormalization,并且是使用NoSQL数据库(如Firebase实时数据库)时的建议方法。主要的缺点,这是数据复制:因此,例如,当用户改变他们所选择的地址,就需要改变:下

  • 用户下address值,
  • users列表地址。

同样,如果允许用户更改他们的用户名,则需要更新其选择的地址以及用户节点下的用户名。

有关处理此问题的详细信息,请参阅this answer which explains a number of methods(虽然示例使用JavaScript,但前提条件仍适用)。

+0

谢谢,我会试试这个。我很抱歉从原帖 – JDoe

+0

我刚刚完成创建FirebaseRecyclerAdapter实例的混淆。我怀疑如何访问用户映射列出我的onBindViewHolder方法中的用户。有任何想法吗? – JDoe

+0

所以你应该可以从'onBindViewHolder()'''''''''''''参数'''''''''''''每个行''地址'模型的一个实例。然后,您可以使用'getUsers()'和[遍历此映射](https://stackoverflow.com/a/1066607)。例如:'for(String username:model.getUsers.values()){textView.append(username +“&”)}'。 – Grimthorr

2

使用FirebaseUI database package可以很方便地从火力地堡实时数据库到应用的UI数据绑定。特别是using FirebaseUI with indexed data适用于您当前的数据库结构。

例如,你会使用类似的东西来:

// keyQuery - the Firebase location containing the list of keys to be found in dataRef 
// dataRef - the Firebase location to watch for data changes. Each key found at 
//   keyRef's location represents a list item. 

Query keyQuery = FirebaseDatabase.getInstance().getReference("/Addresses/Street 10/users"); 
DatabaseReference dataRef = FirebaseDatabase.getInstance().getReference("/User"); 

FirebaseRecyclerOptions<User> options = new FirebaseRecyclerOptions.Builder<User>() 
     .setIndexedQuery(keyQuery, dataRef, User.class) 
     .build(); 

如果您的用户类是:

public class User { 
    private String username; 

    public User() {} 

    public String getUsername() { 
     return this.username; 
    } 

    public void setUsername(String username) { 
     this.username = username; 
    } 

    // ... 
} 

然后,您可以使用上面创建options变量create a FirebaseRecyclerAdapter instance,然后调用startListening()在上面*。

以这种方式使用FirebaseUI将自动处理将/Addresses/Street 10/users下的密钥与/User节点相匹配。


*版本FirebaseUI的2.x使用FirebaseIndexRecyclerAdapter代替并自动开始听,不需要startListening()电话。上述示例适用于3.0版,请参阅FirebaseUI 3.0 upgrade guide

+0

我可以问一下构造函数如何成为public Item? – JDoe

+0

糟糕我的错误!我纠正了它。 – Grimthorr

+0

谢谢你的回答:)我会试试 – JDoe