Ive tried to do it but some of the code runs Asynchronously causing problems, also you cant return a value inside GetReference. I cant use Coroutines they dont return values. This is how far ive gotten.
public string getData(string DataName)
{
string returnDataValue = null;
FirebaseDatabase dbInstance = FirebaseDatabase.DefaultInstance;
dbInstance.GetReference("users").Child(User.UserId).GetValueAsync().ContinueWith(task =>
{
if (task.IsCompleted)
{
DataSnapshot snapshot = task.Result;
returnDataValue = snapshot.Child(DataName).Value.ToString();
}
});
print(returnDataValue);
return returnDataValue;
}
Your method is internally using an async
Task<T>
.
There are basically three options:
Convert the call to a synchronous one and thereby freeze your method until the result comes back.
public string getData(string DataName)
{
FirebaseDatabase dbInstance = FirebaseDatabase.DefaultInstance;
var snapshot = dbInstance.GetReference("users").Child(User.UserId).GetValueAsync().Result;
var returnDataValue = snapshot.Child(DataName).Value.ToString();
print(returnDataValue);
return returnDataValue;
}
I hope I don't have to explain why this is a bad idea;)
Anyway: It will freeze your entire Unity application, until the task is finished. Definitely not what you would want to do!
Make your method await
the result so it can return it.
public async Task<string> getData(string DataName)
{
FirebaseDatabase dbInstance = FirebaseDatabase.DefaultInstance;
var snapshot = await dbInstance.GetReference("users").Child(User.UserId).GetValueAsync();
var returnDataValue = snapshot.Child(DataName).Value.ToString();
print(returnDataValue);
return returnDataValue;
}
The issue with that is
Instead use a callback.
For Unity specific you should not use ContinueWith
but rather ContinueWithOnMainThread
which makes sure the callback is executed in the Unity main thread where you can safely use the Unity API
public void getData(string DataName, Action<string> onSuccess)
{
FirebaseDatabase dbInstance = FirebaseDatabase.DefaultInstance;
dbInstance.GetReference("users").Child(User.UserId).GetValueAsync().ContinueWithOnMainThread(task =>
{
if (task.IsCompleted)
{
DataSnapshot snapshot = task.Result;
returnDataValue = snapshot.Child(DataName).Value.ToString();
print(returnDataValue);
onSuccess?.Invoke(returnDataValue);
}
});
}
So instead of doing something like
var result = getData("someName");
// Do something with result
You would rather pass in a callback action either as a method like
getData("someName", OnSomeDataReceived);
...
private void OnSomeDataReceived (string result)
{
// Do something with result
}
or the same as a Linda expression
getData("someName", result =>
{
// Do something with result
});
If you're ok with using async/await in your code base, you can do this:
public async Task<string> getData(string DataName)
{
FirebaseDatabase dbInstance = FirebaseDatabase.DefaultInstance;
var snapshot = await dbInstance.GetReference("users").Child(User.UserId).GetValueAsync();
// feel free to do additional error checking here first.
return snapshot.Child(DataName).Value.ToString();
print(returnDataValue);
}
There are a number of caveats including:
await getData();
on a background thread it will return in your background thread.GetValueAsync
registers a ValueChanged
listener, waits for it to be called once, then unregisters this listener. If persistence is turned off (this will slow down your game) or this is the first time you retrieve the data, this will likely do what you expect. If persistence is turned on and this data is in the cache, you will get the cached value in GetValueAsync
and the cache will be updated as part of registering the ValueChanged
listener (but you won't get notified since it's been unregistered). When possible, express your code using the ValueChanged
callback in Realtime Database.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.