gpt4 book ai didi

java - 如何返回 DataSnapshot 值作为方法的结果?

转载 作者:行者123 更新时间:2023-12-01 23:42:41 25 4
gpt4 key购买 nike

我对 Java 没有太多经验。我不确定这个问题是否愚蠢,但我需要从 Firebase 实时数据库获取用户名并返回此名称作为此方法的结果。所以,我想出了如何获取这个值,但我不明白如何返回它作为这个方法的结果。最好的方法是什么?

private String getUserName(String uid) {
databaseReference.child(String.format("users/%s/name", uid))
.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
// How to return this value?
dataSnapshot.getValue(String.class);
}

@Override
public void onCancelled(DatabaseError databaseError) {}
});
}

最佳答案

这是异步 Web API 的一个典型问题。您现在无法退回尚未加载的内容。换句话说,您不能简单地创建一个全局变量并在 onDataChange() 方法之外使用它,因为它始终为 null。发生这种情况是因为 onDataChange() 方法被异步调用。根据您的连接速度和状态,可能需要几百毫秒到几秒的时间才能获得数据。

不仅 Firebase 实时数据库会异步加载数据,而且几乎所有现代 Web API 也会异步加载数据,因为这可能需要一些时间。因此,您的主应用程序代码会在辅助线程上加载数据时继续执行,而不是等待数据(这可能会导致用户的应用程序对话框无响应)。然后,当数据可用时,将调用 onDataChange() 方法,并且可以使用该数据。换句话说,当调用 onDataChange() 方法时,您的数据尚未加载。

让我们举个例子,在代码中放置一些日志语句,以便更清楚地了解发生了什么。

private String getUserName(String uid) {
Log.d("TAG", "Before attaching the listener!");
databaseReference.child(String.format("users/%s/name", uid)).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
// How to return this value?
dataSnapshot.getValue(String.class);
Log.d("TAG", "Inside onDataChange() method!");
}

@Override
public void onCancelled(DatabaseError databaseError) {}
});
Log.d("TAG", "After attaching the listener!");
}

如果我们运行这段代码,输出将是:

Before attaching the listener!

After attaching the listener!

Inside onDataChange() method!

这可能不是您所期望的,但它准确地解释了为什么您的数据在返回时为 null

大多数开发人员的最初 react 是尝试“修复”此异步行为,我个人建议不要这样做。网络是异步的,您越早接受这一点,就能越早学习如何利用现代 Web API 提高工作效率。

我发现重新构建这种异步范例的问题是最简单的。我没有说“首先获取数据,然后记录它”,而是将问题描述为“开始获取数据。加载数据后,记录它”。这意味着任何需要数据的代码都必须位于 onDataChange() 方法内部或从内部调用,如下所示:

databaseReference.child(String.format("users/%s/name", uid)).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
// How to return this value?
if(dataSnapshot != null) {
System.out.println(dataSnapshot.getValue(String.class));
}
}

@Override
public void onCancelled(DatabaseError databaseError) {}
});

如果你想在外面使用它,还有另一种方法。您需要创建自己的回调来等待 Firebase 返回数据。要实现此目的,首先,您需要创建一个如下所示的界面:

public interface MyCallback {
void onCallback(String value);
}

然后您需要创建一个实际从数据库获取数据的方法。该方法应如下所示:

public void readData(MyCallback myCallback) {
databaseReference.child(String.format("users/%s/name", uid)).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
String value = dataSnapshot.getValue(String.class);
myCallback.onCallback(value);
}

@Override
public void onCancelled(DatabaseError databaseError) {}
});
}

最后只需调用 readData() 方法,并在需要的地方将 MyCallback 接口(interface)的实例作为参数传递,如下所示:

readData(new MyCallback() {
@Override
public void onCallback(String value) {
Log.d("TAG", value);
}
});

这是您可以在 onDataChange() 方法之外使用该值的唯一方法。欲了解更多信息,您还可以看看这个 video

编辑:2021 年 2 月 26 日

更多信息,您可以查看以下文章:

以及以下视频:

关于java - 如何返回 DataSnapshot 值作为方法的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58252598/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com