为什么调用 API 的函数返回空值或 null 值?

(免责声明:当人们通过 facebook、firebase 等请求使用异步操作时,会出现很多关于数据为空/不正确的问题.我提出这个问题的目的是提供一个简单的为所有开始在 android 中使用异步操作的人回答这个问题)

我正在尝试从我的一项操作中获取数据,当我使用断点或日志对其进行调试时,值在那里,但是当我运行它时,它们始终为空,我该如何解决这个问题?

I'm trying to get data from one of my operations, when I debug it using breakpoints or logs, the values are there, but when I run it they are always null, how can I solve this ?

Firebase

firebaseFirestore.collection("some collection").get()
            .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
                @Override
                public void onSuccess(QuerySnapshot documentSnapshots) {
                     //I want to return these values I receive here? 
            })

脸书

GraphRequest request = GraphRequest.newGraphPathRequest(
            accessToken,
            "some path",
            new GraphRequest.Callback() {
                @Override
                public void onCompleted(GraphResponse response) {
                     //I want to return these values I receive here? 
                }
            });
    request.executeAsync();

等等

推荐答案

什么是同步/异步操作?

好吧,同步等到任务完成.您的代码执行自上而下";在这种情况下.

Well, Synchronous waits until the task has completed. Your code executes "top-down" in this situation.

异步在后台完成一项任务,并在完成时通知您.

Asynchronous completes a task in the background and can notify you when it is complete.

如果您想通过方法/函数从异步操作返回值,您可以在方法/函数中定义自己的回调,以便在这些操作返回时使用这些值.

If you want to return the values from an async operation through a method/function, you can define your own callbacks in your method/function to use these values as they are returned from these operations.

Java 的方法如下

首先定义一个接口:

interface Callback {
    void myResponseCallback(YourReturnType result);//whatever your return type is: string, integer, etc.
}

接下来,将您的方法签名更改为:

next, change your method signature to be like this :

public void foo(final Callback callback) { // make your method, which was previously returning something, return void, and add in the new callback interface.

接下来,无论您以前想在哪里使用这些值,请添加以下行:

next up, wherever you previously wanted to use those values, add this line :

callback.myResponseCallback(yourResponseObject);

举个例子:

@Override
public void onSuccess(QuerySnapshot documentSnapshots) {
    // create your object you want to return here
    String bar = document.get("something").toString();
    callback.myResponseCallback(bar);
})

现在,您之前调用了名为 foo 的方法:

now, where you were previously calling your method called foo:

foo(new Callback() {
        @Override
        public void myResponseCallback(YourReturnType result) {
            //here, this result parameter that comes through is your api call result to use, so use this result right here to do any operation you previously wanted to do. 
        }
    });
}

您如何为 Kotlin 做到这一点?(作为一个基本示例,您只关心单个结果)

How do you do this for Kotlin ? (as a basic example where you only care for a single result)

首先将您的方法签名更改为以下内容:

start off by changing your method signature to something like this:

fun foo(callback:(YourReturnType) -> Unit) {
.....

然后,在您的异步操作结果中:

then, inside your asynchronous operation's result :

firestore.collection("something")
         .document("document").get()
         .addOnSuccessListener { 
             val bar = it.get("something").toString()
             callback(bar)
         }

然后,您之前会调用名为 foo 的方法,现在您可以这样做:

then, where you would have previously called your method called foo, you now do this :

foo() { result->
    // here, this result parameter that comes through is 
    // whatever you passed to the callback in the code aboce, 
    // so use this result right here to do any operation 
    // you previously wanted to do. 
}
// Be aware that code outside the callback here will run
// BEFORE the code above, and cannot rely on any data that may
// be set inside the callback.

如果你的 foo 方法之前接受了参数:

if your foo method previously took in parameters :

fun foo(value:SomeType, callback:(YourType) -> Unit)

您只需将其更改为:

foo(yourValueHere) { result ->
    // here, this result parameter that comes through is 
    // whatever you passed to the callback in the code aboce, 
    // so use this result right here to do any operation 
    // you previously wanted to do. 
}

这些解决方案展示了如何创建一个方法/函数来从您通过使用回调执行的异步操作中返回值.

these solutions show how you can create a method/function to return values from async operations you've performed through the use of callbacks.

但是,重要的是要了解,如果您对为这些创建方法/函数不感兴趣:

However, it is important to understand that, should you not be interested in creating a method/function for these:

@Override
public void onSuccess(SomeApiObjectType someApiResult) {
    // here, this `onSuccess` callback provided by the api 
    // already has the data you're looking for (in this example, 
    // that data would be `someApiResult`).
    // you can simply add all your relevant code which would 
    // be using this result inside this block here, this will 
    // include any manipulation of data, populating adapters, etc. 
    // this is the only place where you will have access to the
    // data returned by the api call, assuming your api follows
    // this pattern
})

相关文章