从 Firebase 中的实时数据库获取数据后,无法写入 Unity 的 TMPro 文本字段
Posted
技术标签:
【中文标题】从 Firebase 中的实时数据库获取数据后,无法写入 Unity 的 TMPro 文本字段【英文标题】:Cannot write to Unity's TMPro text field after getting data from Realtime Database in Firebase 【发布时间】:2020-12-28 11:33:25 【问题描述】:我正在尝试从 Firebase 中的实时数据库中提取数据,然后将该字符串统一放入 TMP_Text 字段中。
在我的代码的 .ContinueWith(task => 部分中写入文本字段似乎存在问题。在 task.isCompleted 中,我可以在将其转换为字符串后获取快照打印值,但是,一旦我尝试写入文本字段,代码就会拖拽。在下面的示例中,输出如下。
-
打印快照,包括键和值
将快照的值打印为字符串
没有错误没有任何事情发生
Value 的第 4 次打印根本不打印
public void PopulateScoreBoard()
FirebaseDatabase.DefaultInstance.GetReference("userlist").Child(LoadingScreen.userID).Child("score").GetValueAsync().ContinueWith(task =>
if (task.IsFaulted)
//handle error
scoreboard.text = "Error!";
else if (task.IsCompleted)
//get snapshot fo data
DataSnapshot snapshot = task.Result;
print(snapshot);
print(snapshot.Value.ToString());
//Get the scoreboard value within the result snapshot
scoreboard.text = snapshot.Value.ToString();
//print the same value to ensure it is working
print(snapshot.Value.ToString());
);
期待获得一些意见,我假设有某种原因您无法在其中写入任何内容,但是,我找不到它。如果是这种情况,我的替代方案是什么?
*更新:似乎在进一步测试之后,您无法在 ContinueWith(task => 中设置任何内容,这正常吗?
【问题讨论】:
【参考方案1】:我能够找到答案,但我仍然希望得到一些意见,看看我是否做得对。
我改成了这段代码,它似乎工作正常。
public void loadData()
FirebaseDatabase.DefaultInstance.GetReference("userlist").ValueChanged += Script_ValueChanged;
private void Script_ValueChanged(object sender, ValueChangedEventArgs e)
scoreboard.text = e.Snapshot.Child(LoadingScreen.userID).Child("userScore").GetValue(true).ToString();
然后在开始时调用它。
【讨论】:
【参考方案2】:首先,我认为您可以通过将 ContinueWith
替换为 ContinueWithOnMainThread
来解决最初的问题:
public void PopulateScoreBoard()
FirebaseDatabase.DefaultInstance.GetReference("userlist").Child(LoadingScreen.userID).Child("score").GetValueAsync().ContinueWithOnMainThread(task =>
if (task.IsFaulted)
//handle error
scoreboard.text = "Error!";
else if (task.IsCompleted)
//get snapshot fo data
DataSnapshot snapshot = task.Result;
print(snapshot);
print(snapshot.Value.ToString());
//Get the scoreboard value within the result snapshot
scoreboard.text = snapshot.Value.ToString();
//print the same value to ensure it is working
print(snapshot.Value.ToString());
);
原因是ContinueWith
会在后台返回。然后执行非线程安全操作scoreboard.text = "Error!";
,这将导致崩溃异常范围内的某些事情。我写过一篇关于这个here的文章。
现在,您的答案更多正确。 GetDataAsync
将注册一个 ValueChanged
侦听器,等待结果,然后取消注册此侦听器。问题在于,这意味着如果您的缓存中有过时数据,您的 GetValueAsync
将是从 Firebase 后端检索到的最后一个值,而不是最新数据。
查看您的代码,您应该做的唯一不同的事情是缓存 "userlist"
引用并稍后取消注册。这与 Unity 如何处理内存和对象生命周期有关 - 在您的代码中可以将文本设置在空对象上:
private DatabaseReference _userListReference;
void Start()
_userListReference = FirebaseDatabase.DefaultInstance.GetReference("userlist");
_userListReference.ValueChanged += Script_ValueChanged;
void OnDestroy()
_userListReference.ValueChanged -= Script_ValueChanged;
private void Script_ValueChanged(object sender, ValueChangedEventArgs e)
scoreboard.text = e.Snapshot.Child(LoadingScreen.userID).Child("userScore").GetValue(true).ToString();
由于current bug,您必须缓存引用以删除事件侦听器。如果您尝试使用 GetReference
再次检索它,您将创建底层对象的第二个 C# 副本,并且事件侦听器将继续存在。
【讨论】:
以上是关于从 Firebase 中的实时数据库获取数据后,无法写入 Unity 的 TMPro 文本字段的主要内容,如果未能解决你的问题,请参考以下文章
如何从 Flutter 中的 Firebase 实时数据库中按 categoryId 获取产品?
如何从 Firebase 实时数据库中获取数据到 Flutter 中的列表中?
如何根据 Angular 6 中的 Firebase 实时数据库中的键获取单个记录