Android Firebase根据群组成员资格创建列表

时间:2016-09-15 02:00:55

标签: android firebase firebase-realtime-database

我正在尝试创建一个仅包含特定组项的列表。例如,我自己在数据库控制台(包括组的键)中创建/编写了“fruits”节点和“groups”节点。

对Firebase来说相对较新,所以仍然试图将数据结构展平。

JSON(显示“水果”和“组”)如下所示:

 {
  "fruits" : {
    "apple" : {
      "color" : "appleColorValueHere",
      "groups" : {
        "GroupABCKey" : true,
        "GroupXYZKey" : true
      },
      "origin" : "appleOriginValueHere",
      "size" : "appleSizeValueHere"
    },
    "orange" : {
      "color" : "orangeColorValueHere",
      "groups" : {
        "GroupABCKey" : true,
        "GroupXYZ" : true
      },
      "origin" : "orangeOriginValueHere",
      "size" : "orangeSizeValueHere"
    },
    "strawberry" : {
      "color" : "strawberryColorValueHere",
      "groups" : {
        "GroupJKLKey" : true
      },
      "origin" : "strawberryOriginValueHere",
      "size" : "strawberrySizeValueHere"
    }
  },
  "groups" : {
    "GroupABCKey" : {
      "members" : {
        "apple" : true,
        "orange" : true
      },
      "name" : "Group ABC Name Here"
    },
    "GroupJKLKey" : {
      "members" : {
        "strawberry" : true
      },
      "name" : "Group JKL Name Here"
    },
    "GroupXYZKey" : {
      "members" : {
        "apple" : true,
        "orange" : true
      },
      "name" : "Group XYZ Name Here"
    }
  }    ...
        ...
}

在应用程序本身中,用户可以创建一个列表,将整个fruits节点复制到新创建的列表中(请参阅user-list-items下面的JSON)。然后我使用FirebaseRecyclerAdapter

显示项目

以下是我如何做的代码:

private void writeNewFruitList(String userId, String username, String email, String title) {
    final String key = databaseReference.child("fruit-lists").push().getKey();
    UserLists userLists = new UserLists(userId, username, email, title);

    HashMap<String, Object> updatedListToAddMap = new HashMap<>();
    HashMap<String, Object> itemToAdd =
            (HashMap<String, Object>) new ObjectMapper().convertValue(userLists, Map.class);
    updatedListToAddMap.put("/fruit-lists/" + key, itemToAdd);
    updatedListToAddMap.put("/user-fruit-lists/" + userId + "/" + key, itemToAdd);

    databaseReference.updateChildren(updatedListToAddMap);

    final DatabaseReference subDatabaseReference = FirebaseDatabase.getInstance().getReference();
    subDatabaseReference.child("fruits").addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            for (DataSnapshot child : dataSnapshot.getChildren()) {
                Log.d(TAG, child.getKey());
                Log.d("fruitValues::", dataSnapshot.getValue().toString());
                final String fruitKey= child.getKey();
                FruitModel fruitModel = child.getValue(FruitModel.class);

                Map<String, Object> nodeValues = fruitModel.toMap();
                Map<String, Object> childUpdates = new HashMap<>();

                String new_path = "/user-list-items/" + key + "/" + fruitKey+ "/";
                childUpdates.put(new_path, nodeValues);
                subDatabaseReference.updateChildren(childUpdates);

            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            Log.e(TAG, "onCancelled", databaseError.toException());
        }
    });
}

问:如何使用群组实施此流程?例如,用户创建列表并且仅希望新创建的列表包含GroupABCKey的果实,但他们也想要那些果实的细节(大小,来源等)。

问题2:编辑我的FruitModel.java帐户的最佳方式是什么?

public class FruitModel {
    public String size;
    public String origin;
    public String color;

    public FruitModel() {
    }

    public FruitModel(String size, String origin, String color) {
        this.size = size;
        this.origin = origin;
        this.color = color;
    }

    @Exclude
    public Map<String, Object> toMap() {
        HashMap<String, Object> result = new HashMap<>();

        result.put("size", size);
        result.put("origin", origin);
        result.put("color", color);

        return result;
    }
    // getters & setters
}

最后,如果正确完成,我认为user-list-items节点 会是什么样子?

listKey1forUserA 是我正确创建的(除了前面提到的映射组)。

listKey2forUserA 是我想要完成的事情 - 用户想要仅使用“GroupJKLKey”中的项目创建和填充列表

  "user-list-items" : {
    "listKey1forUserA" : {
      "apple" : {
        "color" : "appleColorValueHere",
        "groups" : {
          "GroupABCKey" : true,
          "GroupXYZ" : true
        },
        "origin" : "appleOriginValueHere",
        "size" : "appleSizeValueHere"
      },
      "orange" : {
        "color" : "orangeColorValueHere",
        "groups" : {
          "GroupABCKey" : true,
          "GroupXYZKey" : true
        },
        "origin" : "orangeOriginValueHere",
        "size" : "orangeSizeValueHere"
      },
      "strawberry" : {
        "color" : "strawberryColorValueHere",
        "groups" : {
          "GroupJKLKey" : true
        },
        "origin" : "strawberryOriginValueHere",
        "size" : "strawberrySizeValueHere"
      }
    },
    "listKey2forUserA" : {
      "strawberry" : {
        "color" : "strawberryColorValueHere",
        "groups" : {
          "GroupJKLKey" : true
        },
        "origin" : "strawberryOriginValueHere",
        "size" : "strawberrySizeValueHere"
      }
    }
  }

这是解决这个问题的正确方法吗?任何帮助或正确方向上的一点都会很棒。

1 个答案:

答案 0 :(得分:0)

虽然自从我最初发布此问题以来,我的用法略有变化,但下面的两个用例仍适用于一些微小的调整。这可能是一个更好的方法,所以我绝对欢迎来自其他人的任何建议或想法。

tl; dr是您构建数据库的方式,使您拥有groups路径和users路径。 users路径包含对群组的引用。获取特定组的子项的数据快照(只需要键)并将它们添加到ArrayList。 &GT;对于ArrayList中的每个项目,将其插入users路径。

然后,这将允许访问这些用户(或原始问题中使用的水果)的详细信息,以及显示该信息或创建您认为合适的新信息的能力。

根据群组成员资格创建/撰写人员列表

private void writeListFromGroupMembership(){

    final DatabaseReference mainPathReference = FirebaseDatabase.getInstance().getReference();

    final ArrayList<String> groupMembers = new ArrayList<>();

    DatabaseReference groupsReference = FirebaseDatabase.getInstance().getReference()
            .child("groups")
            .child("someOtherChildYouMayHave")
            .child("nameOfGroupYouAreInterestedIn");

    /* Step 1: Get a list of people in a specific group that you are interested in */
    groupsReference.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            for (DataSnapshot child : dataSnapshot.getChildren()) {
                String groupMemberKey = child.getKey();

                if (child.getValue(Boolean.class) != null) {
                    groupMembers.add(groupMemberKey);
                } else {
                    // TODO
                }
            }

            /* Step 2: Loop through your list of people and insert them as a child like the following: */
            for (int i = 0; i < groupMembers.size(); i++) {
                final String singleGroupMember = groupMembers.get(i);

                mainPathReference.child("all-groups").child("anotherChildYouMayHave").child(singleGroupMember)
                        .addListenerForSingleValueEvent(new ValueEventListener() {
                            @Override
                            public void onDataChange(DataSnapshot dataSnapshot) {
                                // Make a POJO for the item and immediately turn it into a HashMap
                                Person person= dataSnapshot.getValue(Person.class);
                                Map<String, Object> nodeValues = person.toMap();

                                // Make a map for the items you are adding
                                Map<String, Object> childUpdates = new HashMap<>();

                                // The path where the items will be copied/written to.
                                String newPath = "/master-list-items/" + listKey + "/" + singleGroupMember + "/";

                                // Add the items to the update map
                                childUpdates.put(newPath, nodeValues);

                                // Do the update
                                mainPathReference.updateChildren(childUpdates);
                            }

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

    // your other onCancelled override method here

}

根据群组成员资格显示人员列表 (例如,使用Spinner):

public List<Person> persons;
...
private void getGroupMembers(String groupSelected) {
    groupRef= FirebaseDatabase.getInstance().getReference()
            .child("someOtherChildThatYouHouseGroupsUnder")
            .child(groupSelected)
            .child("members");

    groupRef.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            for (DataSnapshot child : dataSnapshot.getChildren()) {
                String groupMember= child.getKey();

                selectedGroupMembers.add(groupMember);
            }

            for (int i = 0; i < selectedGroupMembers.size(); i++) {
                String singleMember = selectedGroupMembers.get(i);

                singleMemberDatabaseReference = FirebaseDatabase.getInstance().getReference()
                        .child("all-people")
                        .child(singleMember);

                singleMemberDatabaseReference .addListenerForSingleValueEvent(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        Person person = dataSnapshot.getValue(Person.class);
                        persons.add(person);

                        personAdapter = new PersonAdapter(getApplicationContext(), persons);

                        recyclerView.setAdapter(personAdapter);
                    }

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

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

为了显示基于组成员身份的人员列表,我的数据库结构类似于:

{
   "all-groups":{
      "groupNameorKeyOfGroupName":{
         "details":{
            "meetingLocation":"110 William Street",
            "someOtherChild":"Your value"
         },
         "members":{
            "fakeUserA":true,
            "fakeUserB":true,
            "fakeUserC":true,
            "fakeUserD":true
         }
      }
   }
   "all-users":{
     "fakeUserA":{

     }, 
     "fakeUserB":{

     }
   }
}