I am trying to get User Data in Firebase Firestore, so I pass the UID to the method and it Returns a string (which is my information, like my username). The problem is that the query of firebase is Async, and it results in returning before the query is completed.
How would I work to always return when the query is completed?
public string ReturnUserInfo(string _info, string _key)
{
string returnableValue = "";
Query userQuery = DB.Collection("users").WhereEqualTo("userID", _key);
userQuery.GetSnapshotAsync().ContinueWithOnMainThread(task =>
{
QuerySnapshot snapshot = task.Result;
foreach (DocumentSnapshot documentSnapshot in snapshot.Documents)
{
Dictionary<string, object> user = documentSnapshot.ToDictionary();
foreach (KeyValuePair<string, object> pair in user)
{
if (pair.Key == _info)
returnableValue = pair.Value.ToString();
}
};
});
return returnableValue;
}
CodePudding user response:
You can't directly return something!
The task is executed asynchronously and you directly return ""
since your method immediately continues with the rest of the code while ContinueWithOnMainThread
is executed way later when the task is finished.
You would need to rethink this a little and rather use e.g. a callback like
// pass in a callback to be executed when the information is successfully retrieved
public void ReturnUserInfo(string _info, string _key, Action<string> onSuccess)
{
var userQuery = DB.Collection("users").WhereEqualTo("userID", _key);
userQuery.GetSnapshotAsync().ContinueWithOnMainThread(task =>
{
var snapshot = task.Result;
foreach (DocumentSnapshot documentSnapshot in snapshot.Documents)
{
var user = documentSnapshot.ToDictionary();
// This is btw way better than iterating through the dictionary
if(user.TryGetValue(_info, out var value))
{
// invoke the callback
onSuccess?.Invoke(value.ToString());
// since you are also probably looking for only one result
return;
}
};
});
}
so instead of using e.g.
var result = ReturnUserInfo("xy", "zw");
you rather do
ReturnUserInfo("xy", "zw", result =>
{
// use result here
});
or with a method instead of a lambda
ReturnUserInfo("xy", "zw", OnUserInfoReceived);
...
private void OnUserInfoReceived(string result)
{
// use result here
}