当前位置: 首页 > 面试题库 >

如何通过方法返回DataSnapshot值?

司空鸣
2023-03-14
问题内容

我对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 Realtime Database会异步加载数据,而且几乎所有现代Web API也会异步加载数据,因为这可能需要一些时间。因此,无需等待数据(这可能导致用户无响应的应用程序对话框),而是在将数据加载到辅助线程上的同时继续执行主应用程序代码。然后,当数据可用时,将调用onDataChange()方法,并可以使用该数据。换句话说,通过onDataChange()调用time方法,您的数据尚未加载。

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

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!");
}

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

连接听众之前!

附加监听器后!

里面的onDataChange()方法!

这可能不是您所期望的,但是它恰好说明了为什么null返回数据时会出现数据。

对于大多数开发人员而言,最初的响应是尝试“修复”此问题asynchronous behavior,我个人对此建议。Web是异步的,您越早接受,您就越早学会如何使用现代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返回数据。为此,首先,您需要创建interface如下所示的html" target="_blank">代码:

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()method并将MyCallback接口的实例作为参数传递给您,如您所需要的那样:

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

这是可以在onDataChange()方法外部使用该值的唯一方法。



 类似资料:
  • 问题内容: 我有一个对象,我想知道它的返回类型是否为。 我已经检查了Javadocs,并且有一个返回Class对象的方法。问题是,如果方法无效,他们不会说返回类型是什么。 谢谢! 问题答案: 快速样本:

  • 我希望在我的dao对象中有这样的方法 但我得到了错误 错误:不确定如何将游标转换为此方法的返回类型public abstract java。util。地图 是否可以将其更改为工作版本? 因此,返回的类型可能不同,但主要条件是 数据库中只能有一个查询 我希望避免额外的代码,比如只为这个方法创建额外的数据结构

  • 问题内容: 考虑以下示例(OOP书籍中的典型示例): 我有一Animal堂课,每个人Animal可以有很多朋友。 和子类喜欢Dog,Duck,Mouse等里面加如特定行为bark(),quack()等等。 这是Animal课程: 这是一些带有大量类型转换的代码片段: 有什么办法可以将泛型用于返回类型来摆脱类型转换,所以我可以说 这是一些带有返回类型的初始代码,这些代码作为从未使用过的参数传递给该方

  • 问题内容: 按引用返回的切片为空: 如何通过引用从函数返回切片? 问题答案: 通过分配给,您可以更改指向的位置,而不是指向的值。要做后者,而不是write 。

  • 问题内容: 我需要通过popView将一些数据从secondView发送回First View。如何通过popViewControllerAnimated发回数据? 谢谢! 问题答案: 您可以使用 创建于 在以下位置创建变量 在扩展协议 提供参考的时 在中定义方法 然后您可以从 例 在ChildViewController中 : 在 下面编写代码… 在MainViewController中 有两种