无法从从 Firebase 实时数据库中检索数据以在以下代码行中使用它的方法中获取返回值 [重复]
Posted
技术标签:
【中文标题】无法从从 Firebase 实时数据库中检索数据以在以下代码行中使用它的方法中获取返回值 [重复]【英文标题】:Can't get the return value from a method that retrieves data from Firebase Realtime database to use it in following line of code [duplicate] 【发布时间】:2019-04-17 00:09:49 【问题描述】:我对 Firebase 实时数据库很陌生。我正在开发一个需要从 Firebase Realtime DB 检索数据的 android 应用程序。在大多数情况下,我都能够使用 Firebase 侦听器方法检索数据,但有一次,我发现它无法以我想要的方式获取值(我认为是因为异步性质)。
场景:-
我在 Firebase 实时数据库中有如下数据结构:
评分:
对于用户:
我有一个单独的 java 类 (Suggest.java),它有一个简单的方法来获取用户列表(这里没有显示,因为它是基本实现)和下面定义的方法来从上述评级节点检索数据到一个列表:
public List<String> getMyUnratedPosts(final String currentUserId)
final List<String> currentUserUnratedPosts = new ArrayList<>();
DBRCurrentUnratedList = FirebaseDatabase.getInstance().getReference().child("adRat").child(currentUserId);
DBRCurrentUnratedList.addValueEventListener(new ValueEventListener()
@Override
public void onDataChange(DataSnapshot dataSnapshot)
for (DataSnapshot snapshot : dataSnapshot.getChildren())
AdRat adr = snapshot.getValue(AdRat.class);
int vr = adr.getViewRating();
if(vr < 1)
currentUserUnratedPosts.add(adr.getAdId());
@Override
public void onCancelled(DatabaseError databaseError)
);
return currentUserUnratedPosts;
上面定义的 AdRat 类只是一个具有与上面给出的数据库节点匹配的属性(以及 getter 和 setter)的类。
我正在我活动的 onCreate() 方法中创建此类 (Suggest.java) 的一个实例。然后首先我调用一个方法,在该方法中我只是获取用户列表(与上面获取评级的方法非常相似)。然后在我的活动中的下一行代码我使用 for 循环从我获得的列表中获取每个用户,并将该 userId 用于上面显示的方法。例如,它会是这样的:
Suggest sj = new Suggest();
List<String> users = sj.getUsers();
for (final String mUser: users)
//Just trying to use the user from above here
List<String> myUnratedItems = sj.getMyUnratedPosts(mUser);
Log.d(TAG, "list contains : " + myUnratedItems.toString());
问题:-
当我运行它时,我没有从代码中得到预期的结果。当我调试它时,我会得到用户列表的 null 。我认为由于 firebase 方法是异步的,因此它们不会在下一行代码中准确给出结果(那是我需要它的地方),而是稍后给出结果(但随后程序已经运行在代码行上)我需要这些数据)。
我的整体需求:-
获取用户列表以在下一行代码中使用它(用于下一个方法)。
我已经在 *** 中解决了几个与此相关的问题,但找不到确切的答案。
请解释为什么会发生这种情况以及任何解决方法......
附: : - 我是***的新手,所以请容忍我在撰写问题时犯的任何错误。谢谢。
【问题讨论】:
Firebase 请求是异步的,因此您返回 currentUserUnratedPosts;将始终为 0 或 null,因为您正在尝试返回尚未加载的内容。 请检查副本以了解为什么会出现这种行为以及如何使用自定义回调来解决此问题。 嘿@VandyWhite 通过单击答案旁边的 V 型刻度标记按钮将答案标记为正确,并通过单击答案旁边的向上箭头按钮将其投票,这有助于类似的人关于 Stack Overflow 的问题,我也很感激。干杯! 【参考方案1】:确实,eventListeners
和对 Firebase 的调用具有异步行为,因此您正确理解了您的问题。
不幸的是,我的解决方案(几乎可以肯定有效)是您可能因此不得不改变您的方法。
因此,您应该采用事件驱动的方法。因此,与其“等数据来了,做我的事”,不如“数据进来了,做我的事”。
意思是根据你的问题,首先你应该像你在valueEventListener
的onDataChange()
中正确完成的那样,从Firebase中检索用户列表,然后在它下面做你想做的事情。
问题在于,由于 Firebase 具有异步调用,因此您的数据会在检索之前被打印出来,如果您没有将其初始化为其他内容,显然会是 null
。因此,您所做的所有进一步操作都发生在null
。
因此,您最好在 valueEventListener
本身内执行您的方法或代码。
在你给定的代码中是这样的:
public List<String> getMyUnratedPosts(final String currentUserId)
final List<String> currentUserUnratedPosts = new ArrayList<>();
DBRCurrentUnratedList = FirebaseDatabase.getInstance().getReference().child("adRat").child(currentUserId);
DBRCurrentUnratedList.addValueEventListener(new ValueEventListener()
@Override
public void onDataChange(DataSnapshot dataSnapshot)
for (DataSnapshot snapshot : dataSnapshot.getChildren())
AdRat adr = snapshot.getValue(AdRat.class);
int vr = adr.getViewRating();
if(vr < 1)
currentUserUnratedPosts.add(adr.getAdId());
// do your thing right here
@Override
public void onCancelled(DatabaseError databaseError)
);
return currentUserUnratedPosts;
除此之外,我在搜索时发现的另一种方法是Task.await()
。但是,我不会指望它。
您可以在此处阅读更多相关信息:
*** Question
*** Answer
【讨论】:
【参考方案2】:您完全正确,因为它是由 Firebase 调用的异步性引起的。您最可能想要使用的系统是您“订阅”以了解呼叫何时完成的系统。您可以使用回调函数或其他方法,例如将字段/数据添加到列表中,并让另一个数据结构定期检查列表的更新,以便了解异步调用何时完成。
您的流程可能是这样的:
-
“订阅”异步数据结构
告诉异步数据结构执行
异步调用完成后,执行一些操作。
我建议您查看 Geeksforgeeks 关于 Java 中的异步回调的以下链接:https://www.geeksforgeeks.org/asynchronous-synchronous-callbacks-java/
【讨论】:
以上是关于无法从从 Firebase 实时数据库中检索数据以在以下代码行中使用它的方法中获取返回值 [重复]的主要内容,如果未能解决你的问题,请参考以下文章
无法从unity3d中的firebase实时数据库中检索数据
无法从firebase实时数据库检索数据到recyclerview [重复]