【问题标题】:android firebase query based on query基于查询的android firebase查询
【发布时间】:2016-09-07 23:01:15
【问题描述】:

我正在尝试将朋友 ID 列表从我的 firebase 数据库中提取到我的应用程序中,然后通过在“用户”使用他们的唯一 ID

我的架构如下所示:

{friends
    {
      "Ko2D1of4KxXHzX0OqEZEAKDfw4r2" : {
        "-KR0aTQGT6pfRfB5qIUz" : {
          "friend_id" : "6vFVAAQfwiYERl03C3lzxdPjnEp2"
        },
        "-KR0aaMAOS3FWOAosBmo" : {
          "friend_id" : "kxrQFVjGv0XUHyV5N764Nq50Q3J3"
        }
      }
    }
}

第一个唯一的 ID 是玩家的 ID,可以查询他们的好友列表。的子对象表示关系的ID,其下的friend_id表示其他玩家(朋友)的ID

用户架构如下所示:

{
  "6vFVAAQfwiYERl03C3lzxdPjnEp2" : {
    "emailAddress" : "b@b.com",
    "level" : 1,
    "userName" : "steve"
  },
  "Ko2D1of4KxXHzX0OqEZEAKDfw4r2" : {
    "emailAddress" : "a@a.com",
    "level" : 1,
    "userName" : "bob"
  },
  "kxrQFVjGv0XUHyV5N764Nq50Q3J3" : {
    "emailAddress" : "bg@b.com",
    "level" : 1,
    "userName" : "tim"
  },
  "rNtYvwF8LBhTRM1Wk8ybBJyrFIg2" : {
    "emailAddress" : "c@c.com",
    "level" : 1,
    "userName" : "test account"
  }
}

现在,在我的应用程序中,我可以成功提取所有friend_id 条目,但不知道如何转身并使用此ID 提取有关朋友的其他信息。理想情况下,我可以通过他们唯一的玩家 ID 逐个查询每个朋友,并使用 firebaseListAdapter 填充我拥有的朋友列表片段。

这就是我拉朋友 ID 并填充列表对象的方式。

ValueEventListener friendListener = new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                friendIdList.clear();
                for (DataSnapshot messageSnapshot: dataSnapshot.getChildren()) {
                    String friend_id = (String) messageSnapshot.child("friend_id").getValue();
                    friendIdList.add(friend_id);
                }

            }
            @Override
            public void onCancelled(DatabaseError databaseError) {}
        };
        mDatabase.addValueEventListener(friendListener);

一旦从初始查询中收到 ID,谁能帮我找出最好的方法来提取朋友的所有这些额外信息?

【问题讨论】:

    标签: android firebase firebase-realtime-database listadapter


    【解决方案1】:

    您可以使用 ChildEventListener 获取所有朋友,然后在您的 populateview 或 onBindViewHolder 上使用 ValueEventListener 获取朋友的所有数据。也尝试使用 FirebaseRecyclerView 而不是 FirebaseListView

    【讨论】:

    • 你能扩展这个答案吗?如何让 valueEventListener 响应成功拉取好友 ID 列表?
    【解决方案2】:

    是的,即使我也有同样的困惑。 我们正在苦苦挣扎的是 Contains[*, *, *] 查询。

    即使我也有类似的问题

    /用户{
    “uuid1”:{
    数据1:“值1”
    数据 2:“值 2”
    }
    “uuid2”:{
    数据1:“值1”
    数据 2:“值 2”
    }
    }

    /朋友:{
    uuid1:{
    “uuid2”:真
    ....
    }
    uuid2:{
    “uuid1”:真
    ...
    }
    }

    我的查询是如何使用 FirebaseRecyclerViewAdapter 查询我的朋友列表并展示他们的数据(“/用户”)。

    【讨论】:

      【解决方案3】:

      我建议使用不同的数据结构。这是基于您的数据:

      {
          friends : {
              "Ko2D1of4KxXHzX0OqEZEAKDfw4r2" : {
                  "6vFVAAQfwiYERl03C3lzxdPjnEp2" : true,
                  "kxrQFVjGv0XUHyV5N764Nq50Q3J3" : true
              }
          }
      }
      

      然后遍历他们每个人并拉出他们各自的个人资料。

      【讨论】:

      • 好的,这似乎是一种更合乎逻辑的方式来构建朋友数据。然而,我仍然对如何首先从 firebase 检索这些朋友 ID,然后遍历它们并获得朋友的信息。你能帮我解决这个问题吗?
      • 您不必执行 orderBy,这会使查询更快,并且还可以节省数据库操作,因为您通过索引访问数据。至于循环,我不确定我是否可以帮助解决这个问题,我使用网络上的 firebase。
      【解决方案4】:

      所以我将把 Mathew Berg 和 Pastillas 给出的答案联系起来。根据您的问题和 cmets,我认为它们结合起来可以提供您正在寻找的解决方案。

      数据结构

      您用于用户位置的结构对我来说看起来不错,所以我想说您可以保持原样:

      {
          users: {
             "6vFVAAQfwiYERl03C3lzxdPjnEp2" : {
                  "emailAddress" : "b@b.com",
                  "level" : 1,
                  "userName" : "steve"
              },
             "Ko2D1of4KxXHzX0OqEZEAKDfw4r2" : {
                  "emailAddress" : "a@a.com",
                  "level" : 1,
                  "userName" : "bob"
              }
      
          }
      } 
      

      对于你朋友的位置,我同意马修伯格给出的结构:

      {
          friends : {
              "Ko2D1of4KxXHzX0OqEZEAKDfw4r2" : {
                  "6vFVAAQfwiYERl03C3lzxdPjnEp2" : true,
                  "kxrQFVjGv0XUHyV5N764Nq50Q3J3" : true
              }
          }
      }
      

      仅供参考,您不需要在此结构中使用布尔值。您可以使用任何允许的数据类型作为每个键的值。在这种情况下,键很重要,值只是一个占位符,因为 Firebase 不允许具有空值的键。也就是说,如果您找到使用更有用的值的理由,您可以这样做。在我看来,使用布尔值可以让团队成员或可能跟随你的人更容易阅读结构。

      检索您的数据

      您可以通过多种方式查询朋友列表并获取每个用户的数据。既然你提到在你的问题中使用FirebaseListAdapter,我会同意的。如果您想使用 RecyclerView 和 FirebaseUI,则可以将相同的模式与 FirebaseRecyclerAdapter 一起使用。基本步骤是:

      1. 创建一个指向用户位置的DatabaseReference 你想要谁的朋友列表。

      2. 创建一个指向您用户位置的DatabaseReference

      3. 创建您的FirebaseListAdapter

      4. 当您覆盖 populateView 时,获取每个项目的密钥

      5. 使用addListenersingleValueEvent() 检索每个朋友的用户信息,并使用来自的数据填充您的列表视图行项目 这个查询。

      6. onDataChange of value 事件侦听器中使用每个用户的信息来填充每个列表项的视图。

      DatabaseReference mFriendsRef = FirebaseDatabase.getInstance().getReference().child("friends").child(someUserID;
      
      DatabaseReference mUsersRef = FirebaseDatabase.getInstance().getReference().child("users");
      

      ...

      mAdapter = new FirebaseListAdapter<YourModel>(this, YourModel.class, android.R.your_layout, mFriendsRef) {
          @Override
          protected void populateView(final View view, YourModel model, int position) {
              String key = getRef(position).getKey();
              mUsersRef.child(key).addListenerForSingleValueEvent(new ValueEventListener() {
                          @Override
                          public void onDataChange(DataSnapshot dataSnapshot) {
                              //get data from dataSnapshot and bind to views for each list item 
                          }
      
                          @Override
                          public void onCancelled(DatabaseError databaseError) {
      
                          }
              });     
          }
      };
      
      messagesView.setAdapter(mAdapter);
      

      查看对此问题的评论,了解使用此方法时对性能的担忧:Android Firebase - Denormalized Queries using FirebaseUI

      【讨论】:

      • 今天刚刚有机会实现它,但这正是我所需要的,谢谢!
      【解决方案5】:

      对不起先生,我不知道它是否可以在 FirebaseUI 上运行,但这是我认为有相同问题和相同解决方案的代码,它会显示用户关注者列表,然后如果关注者点击它将打开并将被点击的项目的 id 传递给其他活动。我没有使用 FirebaseUI。

      public class FollowersAdapter extends RecyclerView.Adapter<FollowersAdapter.FollowersHolder>{
      public ArrayList<Follower> followers;
      
      public void addFollower(Follower follower) {
          followers.add(follower);
          notifyItemInserted(getItemCount());
      }
      
      public FollowersAdapter(Context context) {
          this.followers = new ArrayList<>();
          mDatabase = FirebaseDatabase.getInstance().getReference();
          this.fUser = FirebaseAuth.getInstance().getCurrentUser();
      
          mDatabase.child("follower").child(fUser.getUid()).addChildEventListener(new ChildEventListener() {
              @Override
              public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                  Follower follower = dataSnapshot.getValue(Follower.class);
                  addFollower(follower);
              }
      
              @Override
              public void onChildChanged(DataSnapshot dataSnapshot, String s) {
      
              }
      
              @Override
              public void onChildRemoved(DataSnapshot dataSnapshot) {
                  Follower follower = dataSnapshot.getValue(Follower.class);
              }
      
              @Override
              public void onChildMoved(DataSnapshot dataSnapshot, String s) {
      
              }
      
              @Override
              public void onCancelled(DatabaseError databaseError) {
      
              }
          });
      }
      
      @Override
      public FollowersHolder onCreateViewHolder(ViewGroup parent, int position) {
          View view = inflater.inflate(R.layout.followers_model, parent, false);
          FollowersHolder holder = new FollowersHolder(view);
          return holder;
      }
      
      @Override
      public void onBindViewHolder(final FollowersHolder holder, final int position) {
          Query userQuery = mDatabase.child("users").child(followers.get(position).getId());
          userQuery.addValueEventListener(new ValueEventListener() {
              @Override
              public void onDataChange(DataSnapshot dataSnapshot) {
                  user = dataSnapshot.getValue(User.class);
      
                  holder.name.setText(user.getName());
      
                  final Bundle extras = new Bundle();
                  extras.putString(EXTRAS_POSTER_ID, user.getId());
      
                  holder.cont.setOnClickListener(new View.OnClickListener() {
                      @Override
                      public void onClick(View v) {
                          if (!fUser.getUid().equals(user.getId())) {
                              Intent intent = new Intent(context, ViewUserProfile.class);
                              intent.putExtra(EXTRAS_BUNDLE, extras);
                              context.startActivity(intent);
                          }
                      }
                  });
              }
      
              @Override
              public void onCancelled(DatabaseError databaseError) {
      
              }
          });
      }
      
      @Override
      public int getItemCount() {
          return followers.size();
      }
      
      class FollowersHolder extends RecyclerView.ViewHolder {
          View cont;
          TextView name;
      
          public FollowersHolder(View itemView) {
              super(itemView);
      
              cont = itemView.findViewById(R.id.cont_followers);
              name = (TextView) itemView.findViewById(R.id.tv_followers_name);
          }
      }
      

      }

      您使用 childEventListener 获取数据,然后在 onBindViewHolder 或 populateView 添加 onClickListener 并在单击其他活动时传递 id。对不起,先生,我是初学者,哈哈:)

      【讨论】:

        猜你喜欢
        • 2017-05-15
        • 2021-10-28
        • 2019-04-30
        • 2018-11-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-12
        • 1970-01-01
        相关资源
        最近更新 更多