java - 如何在 Firebase-Android 中链接 2 个 EventListener,以便第一个在第二个完成之前不会继续?
问题描述
我正在尝试从侦听器 A 从 Firebase 获取一些数据,然后我将根据从侦听器 A 获得的某些 ID 在侦听器 B 的不同节点下搜索,当我从侦听器 B 接收数据时,我想将其附加到侦听器一个数据。基本上我在 Firebase 中有 2 个节点:帖子和用户。帖子有一些数据和一个用户 ID。当我想显示数据库中的所有帖子时,我将每个帖子添加到 RecyclerView,但在将它们添加到该视图之前,我需要获取一些用户数据,然后(合并这两个收集的数据)将其添加到 recyclerView .
我在网上找不到任何可以尝试的东西(除了一些 UI 阻塞的东西,我宁愿远离,因为我是 Android 新手)。我知道 Firebase 是异步的,Java 没有 Promises 或 async/await,所以 IDK 还有什么可以尝试的。在我目前的实现中,我没有达到我想要的(显然)。
private void initialPopulatePostsFromDB(){
mDatabase.limitToFirst(2).addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
List<IndividualPost> postsDB = new ArrayList<>();
for(DataSnapshot postSnapShot : dataSnapshot.getChildren()){
oldestPostId = postSnapShot.getKey();
final IndividualPost indivPost = postSnapShot.getValue(IndividualPost.class);
indivPost.setContents(typePostContents);
/*
FirebaseDatabase.getInstance().getReference("/users").child(indivPost.getUserId()).addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
userAccount = dataSnapshot.getValue(UserAccount.class);
indivPost.setUserId(userAccount.getName());
System.out.println("[1] ACC NAME: " + indivPost.getUserId());
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
*/
FirebaseDatabase.getInstance().getReference("/users").child(indivPost.getUserId()).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
userAccount = dataSnapshot.getValue(UserAccount.class);
indivPost.setUserId(userAccount.getName());
System.out.println("[1] ACC NAME: " + indivPost.getUserId());
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
System.out.println("[2] ACC NAME: " + indivPost.getUserId());
postsDB.add(indivPost);
System.out.println("[3] ACC NAME: " + indivPost.getUserId());
}
posts.addAll(postsDB);
mAdapter.notifyDataSetChanged();
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
我希望显示新数据,来自用户的数据与帖子相结合。
I expected to be printed:
[1] ACC NAME John
[2] ACC NAME John
[3] ACC NAME John
but it's actually
[2] BniepYpQuh6VgMF6L2
[3] BniepYpQuh6VgMF6L2
[1] John
解决方案
我希望显示新数据,来自用户的数据与帖子相结合。
您没有获得新数据的原因是因为 indivPost
在第二个侦听器中获取用户数据之前,您在第一个侦听器中添加到列表并通知回收视图。这种方式您无法实现您想要的,因为您for loop
是同步的,而侦听器是异步的。更改您的 Firebase 结构以将用户名与帖子一起存储,因此您无需再次调用即可获取用户名。
推荐阅读
- html - 在 AIML 中添加图像
- c++ - gcc 选项 std=gnu++17 与 std=c++17
- c - 当我运行我的代码时,它没有给我任何输出,当我尝试调试它时,它给了我如下所述的错误。需要帮助来解决此问题
- javascript - 如何在 React-intl 日期格式中使用 '-' 而不是 '/'
- swiftui - SwiftUI:编译器无法在合理的时间内对该表达式进行类型检查
- laravel - Laravel Cashier Paddle - 试用天数错误
- security - 避免金融网站dos攻击的最推荐解决方案是什么?
- c++ - 如何将 protobuf 动态消息转换为 C++ 中声明的消息?
- python - django mongodb 使用 djongo 和 pymongo 连接
- maven - 在 spark 类路径中为 mmlspark 添加 jar