Данные загружаются из Cloud Firestore асинхронно, и код после начала загрузки продолжает выполняться.Затем, когда данные загружены, SDK вызывает ваш обработчик завершения.Это означает, что данные доступны только внутри метода onComplete
.Чтобы увидеть, что это значит, запустите ваш код с помощью нескольких операторов журнала, таких как:
System.out.println("Before starting query");
db.collection("Users")
.whereEqualTo("email", email)
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
System.out.println("Got documents");
}
});
System.out.println("After starting query");
Если вы запустите этот код, вы получите:
Перед запуском запроса
После запуска запроса
Получил документы
Вероятно, это не тот порядок, который вы ожидали.Но это прекрасно объясняет, почему тост не отображает имя из базы данных: данные еще не загружены!
Это означает, что любой код, которому нужны данные из базы данных, должен быть (вызван из) внутри метод onComplete()
.Самое простое решение - просто отобразить тост в этом методе:
private void doesExist(String email) {
db.collection("Users")
.whereEqualTo("email", email)
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
name = document.getString("name");
}
Toast.makeText(AddFriend.this, name, Toast.LENGTH_SHORT).show();
}
}
});
}
Это очень просто, но делает ваш doesExist
менее пригодным для повторного использования.Если это проблема, подумайте о создании пользовательского обратного вызова;похож на Task
, но затем посвящен вашему варианту использования здесь.Простой пример этого:
public interface GetUserNameCallback {
void onUserExists(String name);
void onUserDoesNotExist();
}
private void doesExist(String email, UserExistsCallback callback) {
db.collection("Users")
.whereEqualTo("email", email)
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
String name;
for (QueryDocumentSnapshot document : task.getResult()) {
name = document.getString("name");
}
callback.onUserExists(name);
}
else {
callback.onUserDoesNotExist();
}
}
});
}
И затем вызовите его следующим образом:
doesExist(email, new UserExistsCallback() {
@Override
public void onUserExists(String name) {
Toast.makeText(AddFriend.this, name, Toast.LENGTH_SHORT).show();
}
@Override
public void onUserDoesNotExist() {
Toast.makeText(AddFriend.this, "User "+email+" does not exist", Toast.LENGTH_SHORT).show();
}
});
Дополнительные примеры этого см .: