我正在尝试使用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
的值。
答案 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);
});
});
}