如何通过方法返回DataSnapshot值? [英] How to return DataSnapshot value as a result of a method?

查看:132
本文介绍了如何通过方法返回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. With 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 Realtime Database可以异步加载数据,而且几乎所有其他现代Web API都可以异步加载数据,因为这可能需要一些时间.因此,无需等待数据(这可能会导致用户的应用程序对话框无响应),而是在将数据加载到辅助线程上的同时继续执行主应用程序代码.然后,当数据可用时,将调用onDataChange()方法并可以使用该数据.换句话说,到onDataChange()方法被调用时,您的数据尚未加载.

But not only Firebase Realtime Database loads data asynchronously, almost all of modern other web APIs 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. With 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 wil be:

在附加侦听器之前!

Before attaching the listener!

附加监听器后!

在onDataChange()方法内部!

Inside onDataChange() method!

这可能不是您所期望的,但恰恰说明了为什么返回数据时数据为null的原因.

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

对于大多数开发人员而言,最初的响应是尝试并修复"问题. asynchronous behavior,我个人对此建议.网络是异步的,您越早接受它,您就越早学会如何使用现代Web 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.

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

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