(Android 应用程序)有没有办法在 FirebaseRecyclerOptions 查询的 SnapshotParser 部分中从 Firebase 数据库中检索数据?

Posted

技术标签:

【中文标题】(Android 应用程序)有没有办法在 FirebaseRecyclerOptions 查询的 SnapshotParser 部分中从 Firebase 数据库中检索数据?【英文标题】:(Android App) Is there a way to retrieve data from a Firebase database while inside the SnapshotParser part of the FirebaseRecyclerOptions query? 【发布时间】:2020-12-19 02:30:24 【问题描述】:

因此,正如标题所述,我希望先从 Firebase 数据库中检索数据,然后再在 FirebaseRecyclerOptions 中构造要在 FirebaseRecyclerAdapter 中使用的对象。基本上,我想做的是在我正在开发的应用程序中创建一个朋友列表。这是数据库的样子:

Friends:
  uid1:
    id: friendID
  uid2:
    id: friendID

Users:
  uid1:
    name: name
    status: status
    image: profileImageUrl
  uid2:
    name: name
    status: status
    image: profileImageUrl

我的代码目前看起来像这样:

FirebaseRecyclerOptions<Users> options = new FirebaseRecyclerOptions.Builder<Users>().setQuery(usersDatabase, new SnapshotParser<Users>() 
        @NonNull
        @Override
        public Users parseSnapshot(@NonNull DataSnapshot snapshot) 
            System.out.println(snapshot);
            rootRef.child("Users").child(snapshot.getValue().toString()).addValueEventListener(new ValueEventListener() 
                @Override
                public void onDataChange(@NonNull DataSnapshot dataSnapshot) 
                    System.out.println(dataSnapshot);
                    name = dataSnapshot.child("name").getValue().toString();
                    status = dataSnapshot.child("status").getValue().toString();
                    image = dataSnapshot.child("image").getValue().toString();
                    return;
                

                @Override
                public void onCancelled(@NonNull DatabaseError databaseError) 

                
            );
            System.out.println(snapshot);
            return new Users(name, image, status);
        
    ).build();

问题是我添加的 ValueEventListener 直到返回新的 Users 实例后才会触发。我应该将 ValueEventListener 添加到与 FirebaseRecyclerOptions 查询相同的 DatabaseReference (userDatabase) 中吗?

【问题讨论】:

【参考方案1】:

FirebaseUI 无法真正实现您想要做的事情。快照解析器需要立即或同步返回一个用户对象。您无法执行异步数据库查询(不会立即完成,甚至根本无法保证完成)来提供该值。

如果您需要执行多个查询以填充视图,您将无法有效地使用 FirebaseUI。您可能应该考虑提前进行所有查找,或者编写一个特殊的适配器,允许在结果可用时异步填充视图内容。这最终需要大量代码才能正确完成。

【讨论】:

嗯...好的,谢谢。我将如何创建自己的适配器?我应该为它扩展 FirebaseRecyclerAdapter 或 FirebaseRecyclerAdapter.Builder 吗? FirebaseUI 类对您完全没有帮助。你必须从头开始构建它(这将是相当多的工作)。 哦。我知道了。我要做的是从 Firestore 中当前用户的文档中获取好友列表,然后使用检索到的 ID 再次查询数据库以获取每个用户的图标、名称和状态。似乎很奇怪,他们没有某种方法来进行这样的嵌套查询。使用从数据库中其他地方提取的数据来检索另一条信息是很常见的事情。 FirebaseUI 组件用于引导最基本的案例以轻松上手。当事情变得更复杂时(就像您现在所做的那样),实用程序包装器的有用性会随着可变性的增加而下降 - 有太多不同且特定的用例无法轻松包装。 确实如此。我想我太习惯使用 SQL 数据库了。感谢您的帮助。【参考方案2】:

回答我自己的问题似乎有点多余,但这主要适用于其他有此问题的人。按照@Doug Stevenson 的建议,我开始尝试制作自己的自定义回收器适配器和选项类。但是,我意识到可以修改选项的查询。所以基本上,解决方案是这样的:

Query query = database.collection("Users");

@Override
protected void onStart() 
    super.onStart();
    String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
    DocumentReference ref = FirebaseFirestore.getInstance().collection("Users").document(uid);
    ref.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() 
        @Override
        public void onComplete(@NonNull Task<DocumentSnapshot> task) 
            if (task.isSuccessful())
                DocumentSnapshot document = task.getResult();
                if (document.exists()) 
                    friends = (ArrayList<String>) document.get("friends");
                    if (friends.size() > 0) 
                        FirestoreRecyclerOptions<Users> options = new FirestoreRecyclerOptions.Builder<Users>().setQuery(query.whereIn("user_id", friends), Users.class).build();
                        FirestoreRecyclerAdapter<Users, UsersViewHolder> adapter = new FirestoreRecyclerAdapter<Users, UsersViewHolder>(options) 
                            @Override
                            public UsersViewHolder onCreateViewHolder(ViewGroup parent, int viewType) 
                                View view = LayoutInflater.from(parent.getContext())
                                        .inflate(R.layout.single_user_layout, parent, false);
                                return new UsersViewHolder(view);
                            

                            @Override
                            protected void onBindViewHolder(@NonNull UsersViewHolder usersViewHolder, int i, @NonNull Users users) 
                                if (users != null) 
                                    usersViewHolder.setName(users.name);
                                    usersViewHolder.setStatus(users.status);
                                    usersViewHolder.setImg(users.image);

                                    final String userID = getSnapshots().getSnapshot(i).getId();
                                    usersViewHolder.mView.setOnClickListener(new View.OnClickListener() 
                                        @Override
                                        public void onClick(View view) 
                                            Intent profilePage = new Intent(FriendsList.this, ProfileActivity.class);
                                            profilePage.putExtra("userID", userID);
                                            startActivity(profilePage);
                                        
                                    );
                                
                            
                        ;
                        usersListPage.setAdapter(adapter);
                        adapter.startListening();
                    
                
            
        
    );

在 setQuery 方法中,我没有使用集合引用作为查询,而是从中创建了一个查询对象,然后修改了查询 query.whereIn(),它允许您检查文档的字段是否包含给定对象或列表中的对象之一。

我知道我这里的代码很乱。

【讨论】:

以上是关于(Android 应用程序)有没有办法在 FirebaseRecyclerOptions 查询的 SnapshotParser 部分中从 Firebase 数据库中检索数据?的主要内容,如果未能解决你的问题,请参考以下文章

在 kindle fire 上调试安卓应用

我可以在为 kindle fire 商店发布的应用程序中使用谷歌分析吗?

Fire-base 卡住并且无法与 android studio 连接

如何区分 Android 应用程序是不是在 Amazon Kindle Fire 上运行?

在 Amazon Fire TV 应用商店上兼容/提供 Android TV 应用程序有多难?

如何在 Android 中放置正确的应用程序图标大小,包括 Amazon Kindle Fire?