如何从Android中的Firebase实时数据库中检索数据?

时间:2017-02-27 13:57:21

标签: android firebase firebase-realtime-database

我是新来的。我无法从Firebase数据库中检索数据。我想检索每个类别的名称和food_items

MyDatabase的

{
    "categories" : {
        "category1" : {
          "name" : "Babyfood"
        },
        "category2" : {
          "name" : "Dairy"
        },
        "category3" : {
          "food_items" : {
            "item1" : true,
            "item2" : true
          },
          "name" : "Fruits"
        }
      },
      "food_items" : {
        "item1" : {
          "category" : "category3",
          "name" : "Apple"
        },
        "item2" : {
          "category" : "category3",
          "name" : "Banana"
        }
    }
}

FoodCategory.java

public class FoodCategory implements Serializable{

    String name;
    FoodItem food_items;

    public FoodCategory(){}

    public FoodCategory(String name,  FoodItem food_items) {
        this.name = name;
        this.food_items = food_items;
    }

    public FoodItem getFoodItems() {
        return food_items;
    }

    public String getName() {
        return name;
    }

    public FoodCategory(FoodCategory category){
        this.name = category.getName();
        this.food_items = category.getFoodItems();
    }

}

FoodItem.java

public class FoodItem {
    String name;

    public FoodItem( FoodItem foodItem) {
        this.name = foodItem.getName();
    }

    public String getName() {
        return name;
    }
}

以下是我检索每个类别数据的代码

mRootRef = FirebaseDatabase.getInstance().getReference();
    mCategoryRef = mRootRef.child("categories");
    mCategoryRef.addValueEventListener(new ValueEventListener() {

        ArrayList<FoodCategory> values = new ArrayList<>();
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            for (DataSnapshot snapshot: dataSnapshot.getChildren()){
                FoodCategory c = snapshot.getValue(FoodCategory.class);
                Log.d("Categories: ", c.name + " " + c.food_items);
                values.add(c);
            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

它返回类别名称的正确值,但food_items为空。

2 个答案:

答案 0 :(得分:0)

对于迭代节点的所有子节点,请改用ChildEventListener。 不要对方法名称&#39; onChildAdded&#39;感到困惑。 ,它将第一次进入所有条目。

    mCategoryRef.addChildEventListener(new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String s) {
            FoodCategory c = dataSnapshot.getValue(FoodCategory.class);
            Log.d("Categories: ", c.name + " " + c.food_items);
            values.add(c);
        }

        @Override
        public void onChildChanged(DataSnapshot dataSnapshot, String s) {

        }

        @Override
        public void onChildRemoved(DataSnapshot dataSnapshot) {

        }

        @Override
        public void onChildMoved(DataSnapshot dataSnapshot, String s) {

        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

来源:https://firebase.google.com/docs/database/android/lists-of-data

答案 1 :(得分:0)

在您的FoodCategory模型中,您提到它只有 SINGLE FoodItem

public class FoodCategory implements Serializable{
    String name;
    FoodItem food_items;
    ...
}

通过查看您的数据库结构,它应该是FoodItem的列表/数组对吗?如果你的FoodItem只包含名称字符串作为键,布尔值作为值(它总是为真,对吗?)那么你可能应该把它作为HashMap,就像这样

public class FoodCategory implements Serializable{
    String name;
    HashMap<String, Boolean> food_items;
    ...
}

这样,您不需要FoodItem自定义对象。 (或者你仍然可以使用它并使food_items成为FoodItem自定义对象的列表/数组。

修改

看起来原始海报神奇地“知道”该做什么并自己回答(嗯?)。但是对于那些有同样问题并在这里寻找答案的人来说,这个解释适合你。

数据库结构:

{
    "categories" : {
        "category1" : {
          "name" : "Babyfood"
        },
        "category2" : {
          "name" : "Dairy"
        },
        "category3" : {
          "food_items" : {
            "item1" : true,
            "item2" : true
          },
          "name" : "Fruits"
        }
      },
      "food_items" : {
        "item1" : {
          "category" : "category3",
          "name" : "Apple"
        },
        "item2" : {
          "category" : "category3",
          "name" : "Banana"
        }
    }
}

在发布的相关代码示例中,它会读取categories上的值并搜索categories/???/food_items的值。请注意,我在此处提到的food_itemscategories而非food_itemsitem1item2内的{/ 1}}。

当然,对于第一个和第三个孩子,它将包含null,因为它实际上没有价值。但第二个将有2个值:

{ "item1":true, "item2":true }
  

注意:它有2个值,因此我建议使用HashMap来阅读它,因为原始海报会将其读作单个值。

从那里,我们知道出了什么问题。之后,您可能希望获得item1item2的详细信息,因为它只包含布尔值(它就像sql中的外键)。那么你应该阅读价值food_items/???然后你就去了。