【问题标题】:Android - Querying data from FirebaseAndroid - 从 Firebase 查询数据
【发布时间】:2018-04-16 02:18:18
【问题描述】:

我的 Firebase 实时数据库中有想要查询并显示在 Recyclerview 中的数据,但我对如何执行此操作感到困惑。

数据库结构:

对于一项活动,我只想查询标记节点。 使用 FirebaseUI 似乎很容易做到这一点

对于另一个活动,我想查询所有路线和所有标记。所以我的 recyclerview 中的每一行都包含:一条路线的 startDestination 和 endDestination,连接到该路线的标记的地址和时间

【问题讨论】:

    标签: android firebase firebase-realtime-database


    【解决方案1】:

    这是我之前的回答 herehere 的后续,所以我会尽力为您提供一些示例。

    创建可扩展的数据

    这里的基本前提是,在显示路线列表时,您要尽量避免下载与路线标记相关的所有数据。这是因为此时您不需要了解有关标记的所有信息,只需了解部分细节即可。

    此外,您从数据库(通过网络)下载的用于显示路线列表的数据越少,该列表的组成就越快。例如,假设您有 1000 条路线,每条路线有 10 个标记;这意味着下载 1000 条路线和 10000 个标记只是为了显示路线列表。

    这就是 documentation suggests using data fanout 创建可扩展数据的原因,也建议 denormalize 在 NoSQL 数据库中复制数据。

    数据重复

    因此,为了快速轻松地获得与特定路线相关的可用标记列表,您需要开始在路线节点上存储标记地址和时间,就像使用标记 ID 一样。

    对此的一种可能解决方案是创建一个额外的PartialMarker 类,其中包含有关用于路由列表的标记的有限信息:

    public class PartialMarker {
        private String address;
        private String time;
    
        public PartialMarker() {}
    
        public PartialMarker(String address, String time) {
            this.address = address;
            this.time = time;
        }
    
        public String getAddress() { return address; }
    
        public String getTime() { return time; }
    }
    

    然后在你的Route 类下有一个Map

    public Route {
        // ...
    
        private HashMap<String, PartialMarker> partialMarkers = new HashMap<>();
    
        public HashMap<String, PartialMarker> getPartialMarkers() { return partialMarkers; }
    }
    

    因此,当您将新标记保存到路线的数据库中时,您还将为每个标记创建一个 PartialMarker 实例并将其保存到路线节点,例如:

    public void saveToDatabase() {
        // Do your thing to save the route
    
        // Create some partial markers
        HashMap<String, Object> partialMarkers = new HashMap<>();
        for (Map.Entry<String, Object> entry : markers.entrySet()) {
            String key = entry.getKey();
            FirebaseMarker marker = (FirebaseMarker) entry.getValue();
            partialMarkers.put(key, new PartialMarker(marker.getAddress(), marker.getTime()));
        }
    
        // Store the partial markers under the route
        schoolReference.child("routes").child(routeId).child("partialMarkers").updateChildren(partialMarkers);
    }
    

    然后,当您将Route 绑定到RecyclerView 中的ViewHolder 时,您可以遍历每个PartialMarker 以在该行上显示它们的列表:

    for (PartialMarker partialMarker : model.getPartialMarkers().values()) {
        // ...
    }
    

    结论

    您可以通过任何其他方式做到这一点,但我希望这能让您深入了解使用非规范化数据实现这一目标的可能方法。一开始很难理解,因为数据的复制似乎是倒退的,但这是 NoSQL 数据库的建议模式,当您开始处理大量数据时,它是有意义的。

    【讨论】:

    • 感谢您的回答。 partialMarkers.push 是一个 hashmap 引用,因为没有 push 方法可用于 partialMarkers?我假设你的意思是put
    • 糟糕,抱歉,应该是 put() 添加到 Map,我混淆了地图和参考资料!
    • 我认为它几乎可以工作。我已经通过查询完成了最后一部分,但我得到了一个例外:NullPointerException: Attempt to invoke virtual method 'java.util.Collection java.util.HashMap.values()' on a null object reference。我在此 pastebin 的第 87 行收到此错误:pastebin.com/ZsPGJNrz
    • 这可能是因为并非所有路由在数据库中都有partialMarkers 值,因此您可能希望在Route 类中初始化HashMap 以避免此错误,请参阅我的编辑。
    • 一个小问题。例如,当我向地图添加 5 个标记时,partialMarkers 节点仅显示 4 个。当我添加 3 个标记时,partialMarkers 节点下只有 2 个子节点。它总是缺少一个。
    猜你喜欢
    • 2017-09-20
    • 2017-10-11
    • 1970-01-01
    • 2020-09-08
    • 2017-09-22
    • 1970-01-01
    • 2022-10-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多