通过操作回调从实时数据库中检索数据

时间:2018-11-16 10:14:54

标签: c# firebase unity3d firebase-realtime-database

我正在尝试使用Unity从Firebase的实时数据库接收JSON值。

我执行以下操作:

   FirebaseDatabase.DefaultInstance
          .GetReference("Leaders").OrderByChild("score").GetValueAsync().ContinueWith(task =>
                    {
                        if (task.IsFaulted)
                        {
                            Debug.LogError("error in reading LeaderBoard");
                            return;
                        }
                        else if (task.IsCompleted)
                        {
                            Debug.Log("Received values for Leaders.");
                            string JsonLeaderBaord = task.Result.GetRawJsonValue();
                            callback(JsonLeaderBaord);
                        }
        }
  });

尝试读取回调:

private string GetStoredHighScores()
    {
      private string JsonLeaderBoardResult;
      DataBaseModel.Instance.RetriveLeaderBoard(result =>
            {
                JsonLeaderBoardResult = result; //gets the data

            });
  return JsonLeaderBoardResult; //returns Null since it doesn't wait for the result to come.
}

问题是我如何等待回调返回值,然后之后 return JsonLeaderBoardResult的值。

2 个答案:

答案 0 :(得分:0)

您会看到与异步API的经典混淆。由于从Firebase加载数据可能需要一些时间,因此它是异步发生的(在单独的线程上)。这样,当Firebase客户端正在等待服务器的响应时,主代码就可以继续。当数据可用时,Firebase客户端会使用该数据调用您的回调方法,以便您可以对其进行处理。

通过放置一些日志记录语句,最容易在代码中查看其作用:

Debug.Log("Before starting to load data");
FirebaseDatabase.DefaultInstance
      .GetReference("Leaders").OrderByChild("score").GetValueAsync().ContinueWith(task => {
    Debug.Log("Got data");

    }
});
Debug.Log("After starting to load data");

运行此代码时,它会打印:

  

开始加载数据之前

     

开始加载数据后

     

获得数据

这可能不是您期望输出的顺序。由于对Firebase的调用具有异步特性,因此第二条日志行最后被打印。这正好解释了为什么返回时会看到一个空数组:当时尚未从Firebase加载数据,而您的ContinueWith尚未执行。

解决方案始终相同:由于您无法返回尚未加载的数据,因此必须实现一个回调函数。您共享的代码已经执行了两次:一次用于Firebase本身的ContinueWith,另一次用于RetriveLeaderBoard

任何需要最新排行榜的代码,基本上都必须调用RetriveLeaderBoard并对其回调中的排行榜数据进行任何处理。例如,如果要打印排行榜:

DataBaseModel.Instance.RetriveLeaderBoard(result => {
    Debug.Log(result);
});

答案 1 :(得分:0)

  

return JsonLeaderBoardResult; //由于不等待而返回Null   为了结果。

RetriveLeaderBoard函数不会立即返回。您可以使用协程等待它,也可以通过JsonLeaderBoardResult返回Action结果。在您的情况下,使用Action更有意义。

将字符串返回类型更改为void,然后通过Action返回结果:

private void GetStoredHighScores(Action<string> callback)
{
    string JsonLeaderBoardResult;
    DataBaseModel.Instance.RetriveLeaderBoard(result =>
            {
                JsonLeaderBoardResult = result; //gets the data
                if (callback != null)
                    callback(JsonLeaderBoardResult);
            });
}

用法:

GetStoredHighScores((result) =>
{
    Debug.Log(result);
});

编辑:

  

那太好了,但是在获得   导致动作之外的“ GetStoredHighScores”,否则我可以   出现错误:get_transform只能从主调用   线程。

您收到此错误,因为RetriveLeaderBoard正在另一个线程上运行。从this中获取UnityThread,然后使用UnityThread.executeInUpdate在主线程上进行回调。

您的新代码:

void Awake()
{
    UnityThread.initUnityThread();
}

private void GetStoredHighScores(Action<string> callback)
{
    string JsonLeaderBoardResult;
    DataBaseModel.Instance.RetriveLeaderBoard(result =>
            {
                JsonLeaderBoardResult = result; //gets the data

                UnityThread.executeInUpdate(() =>
                {
                    if (callback != null)
                        callback(JsonLeaderBoardResult);
                });
            });
}