在 Android 中从 Firebase 实时数据库中检索数据

新手上路,请多包涵

我是 Firebase 和 NoSQL 的新手。我有一个 Android 演示,带有一个城市自动完成文本字段,我想在其中填充我从 Firebase 数据库中输入的城市。

 {   "cities":{
        "Guayaquil":true,
        "Gualaceo":true,
        "Quito":true,
        "Quevedo":true,
        "Cuenca":true,
        "Loja":true,
        "Ibarra":true,
        "Manta":true
    }
}

这是我到目前为止所拥有的。

如何从以字母开头的数据库城市中检索(从键盘输入)?如果我开始输入“G”,我想收到“Guayaquil”和“Gualaceo”。

如果我使用 orderByValue 总是返回一个空快照。

如果我使用 orderByKey 返回整个列表。

     Query citiesQuery = databaseRef.child("cities").startAt(input).orderByValue();
    citiesQuery.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            List<String> cities = new ArrayList<String>();
            for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) {
                cities.add(postSnapshot.getValue().toString());
            }

注: 如能推荐更好的数据结构,不客气。

原文由 Erick Medina 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 377
2 个回答

@NicholasChen 已经确定了问题所在。但这是您使用 3.x SDK 实现的方式:

 DatabaseReference cities = databaseRef.child("cities")
Query citiesQuery = cities.orderByKey().startAt(input).endAt(input+"\uf8ff");
citiesQuery.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        List<String> cities = new ArrayList<String>();
        for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) {
            cities.add(postSnapshot.getValue().toString());
        }

通过从用户输入开始并以用户输入开头的最后一个字符串结束,您将获得所有匹配项

对于相对较短的项目列表,Ryan 的方法也很有效。但是上面的 Firebase 查询将过滤服务器端。

更新

我刚刚运行了这段代码:

     DatabaseReference databaseRef = FirebaseDatabase.getInstance().getReference("39714936");

    String input = "G";

    DatabaseReference cities = databaseRef.child("cities");
    Query citiesQuery = cities.orderByKey().startAt(input).endAt(input + "\uf8ff");
    citiesQuery.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            List<String> cities = new ArrayList<String>();

            for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
                cities.add(postSnapshot.getValue().toString());
            }
            System.out.println(cities);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

它打印:

真的

真的

如此明显匹配两个城市。

随意测试我的数据库: https ://stackoverflow.firebaseio.com/39714936

原文由 Frank van Puffelen 发布,翻译遵循 CC BY-SA 4.0 许可协议

尝试这样的事情来迭代 cities 快照中的子项,并将所有城市添加到 ArrayListStrings 中。

 ArrayList<String> cityList = new ArrayList<>();

databaseRef.child("cities").addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        cityList.clear();
        for (DataSnapshot data : dataSnapshot.getChildren()){
            cityList.add(data.getKey);
        }

    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        Log.w(TAG, "getUser:onCancelled", databaseError.toException());
        // ...
    }
});

为清楚起见编辑本段:

这会将所有城市读入程序内存,以便您可以使用该数据向用户显示城市。如果城市列表发生变化,用户看到的数据也会发生变化。如果用户不在线,这将不起作用。这在数据库上放置了一个实时的、仅在线的监听器。

我脑海中的逻辑是这样的:

  1. 在文本框上设置值侦听器。
  2. 当用户键入时,使视图显示数组列表中以与键入的相同子字符串开头的所有项目。
  3. 当然要处理 arrayIndex 错误。

希望这会让你走上正轨。我相信还有其他方法可以实现它,但这是我个人会做的。如果您在显示正确城市的代码方面需要帮助,请开始与我聊天,我可以与您一起集思广益。

原文由 Ryan 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题