如何作为方法的结果返回 DataSnapshot 值? [英] How to return DataSnapshot value as a result of a method?

查看:23
本文介绍了如何作为方法的结果返回 DataSnapshot 值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I don't have much experience with Java. I'm not sure if this question is stupid, but I need to get a user name from Firebase realtime database and return this name as a result of this method. So, I figured out how to get this value, but I don't understand how to return it as result of this method. What's the best way to do this?

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() 方法被称为异步.根据您的连接速度和状态,该数据可能需要几百毫秒到几秒才能可用.

This is a classic issue with asynchronous web APIs. You cannot return something now that hasn't been loaded yet. In other words, you cannot simply create a global variable and use it outside onDataChange() method because it will always be null. This is happening because onDataChange() method is called asynchronous. Depending on your connection speed and the state, it may take from a few hundred milliseconds to a few seconds before that data is available.

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

But not only Firebase Realtime Database loads data asynchronously, but almost all modern web APIs also do, since it may take some time. So instead of waiting for the data (which can lead to unresponsive application dialogs for your users), your main application code continues while the data is loaded on a secondary thread. Then when the data is available, your onDataChange() method is called, and can use the data. In other words, by the time onDataChange() method is called your data is not loaded yet.

我们举个例子,通过在代码中放置几条日志语句,更清楚地看到发生了什么.

Let's take an example, by placing a few log statements in the code, to see more clearly what's going on.

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

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

If we run this code will, the output will be:

在附加监听器之前!

附加监听器后!

在 onDataChange() 方法中!

Inside onDataChange() method!

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

This is probably not what you expected, but it explains precisely why your data is null when returning it.

大多数开发人员的最初反应是尝试修复"这种异步行为,我个人建议不要这样做.网络是异步的,您越早接受这一点,您就能越早了解如何使用现代网络 API 提高工作效率.

The initial response for most developers is to try and "fix" this asynchronous behavior, which I personally recommend against this. The web is asynchronous, and the sooner you accept that the sooner you can learn how to become productive with modern web APIs.

我发现为这种异步范式重构问题最容易.我没有说首先获取数据,然后记录它",而是将问题定义为开始获取数据".当数据被加载时,记录它".这意味着任何需要数据的代码都必须在 onDataChange() 方法内部或从那里调用,如下所示:

I've found it easiest to reframe problems for this asynchronous paradigm. Instead of saying "First get the data, then log it", I frame the problem as "Start to get data. When the data is loaded, log it". This means that any code that requires the data must be inside onDataChange() method or called from inside there, like this:

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:

If you want to use that outside, there is another approach. You need to create your own callback to wait for Firebase to return you the data. To achieve this, first, you need to create an interface like this:

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

然后你需要创建一个方法,它实际上是从数据库中获取数据.此方法应如下所示:

Then you need to create a method that is actually getting the data from the database. This method should look like this:

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 接口的实例作为参数传递给您需要的地方,如下所示:

In the end just simply call readData() method and pass an instance of the MyCallback interface as an argument wherever you need it like this:

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

这是您可以在 onDataChange() 方法之外使用该值的唯一方法.如需了解详情,您还可以观看此视频.

This is the only way in which you can use that value outside onDataChange() method. For more information, you can take also a look at this video.

2021 年 2 月 26 日

Feb 26th, 2021

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

For more info, you can check the following article:

还有以下视频:

这篇关于如何作为方法的结果返回 DataSnapshot 值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆