Проблема не столько в многопоточности, сколько в том, что данные загружаются из Firebase асинхронно. К тому времени, когда ваша функция updateUI
проверяет значение aa
, onComplete
еще не запускается.
Это легче всего увидеть, разместив несколько удачно расположенных операторов логирования:
System.out.println("Before attaching listener");
docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
@Override
public void onComplete(@NonNull Task<DocumentSnapshot> task) {
System.out.println("Got document");
}
});
System.out.println("After attaching listener");
Когда вы запускаете этот код, он печатает
Перед подключением слушателя
После подключения слушателя
Получил документ
Вероятно, это не то, что вы ожидали, но оно точно объясняет, почему aa
остается неизменным, когда updateUI
проверяет его. Документ еще не был прочитан из Firestore, поэтому onComplete
еще не запущен.
Решением для этого является перемещение всего кода, требующего данных из базы данных , в метод onComplete
. Самый простой способ в вашем случае:
public void userExists(String uid) {
FirebaseFirestore db = FirebaseFirestore.getInstance();
DocumentReference docRef = db.collection("users").document(uid);
docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
@Override
public void onComplete(@NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot documentSnapshot = task.getResult();
if (documentSnapshot.exists()) {
//Fill layout with the user data and the user linked document data
//USER DATA
txvNombre=findViewById(R.id.nombrePerfil);
txvNombre.setText(user.getDisplayName());
imvAvatar=findViewById(R.id.imvVistaPerfilAvatar);
Picasso.with(VistaPerfilActivity.this)
.load(user.getPhotoUrl())
.resize(500,500)
.centerCrop()
.into(imvAvatar);
//HERE GOES THE DOCUMENT DATA
}
}
}
});
}
Теперь ваш код, который нуждается в документе, запускается только после того, как документ действительно доступен. Это будет работать, но делает функцию userExists
несколько менее пригодной для повторного использования. Если вы хотите это исправить, вы можете передать обратный вызов в userExists
, который вы затем вызовете после загрузки документа.
public interface UserExistsCallback {
void onCallback(boolean isExisting);
}
И используйте это в userExists
как:
public void userExists(String uid, final UserExistsCallback callback) {
FirebaseFirestore db = FirebaseFirestore.getInstance();
DocumentReference docRef = db.collection("users").document(uid);
docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
@Override
public void onComplete(@NonNull Task<DocumentSnapshot> task) {
boolean userExists = false;
if (task.isSuccessful()) {
DocumentSnapshot documentSnapshot = task.getResult();
userExists = documentSnapshot.exists();
}
callback.onCallback(userExists);
}
});
}
И затем вызвать это из updateUI
с помощью:
if (user != null) {
userExists(user.getUid(), new UserExistsCallback() {
public void onCallback(boolean isExisting) {
if(isExisting){
//Fill layout with the user data and the user linked document data
//USER DATA
txvNombre=findViewById(R.id.nombrePerfil);
txvNombre.setText(user.getDisplayName());
imvAvatar=findViewById(R.id.imvVistaPerfilAvatar);
Picasso.with(VistaPerfilActivity.this)
.load(user.getPhotoUrl())
.resize(500,500)
.centerCrop()
.into(imvAvatar);
//HERE GOES THE DOCUMENT DATA
}else{
}
} else {
finish();
}
});
}
Как вы можете видеть, наш `` обратный вызов очень похож на OnCompleteListener
самого Firestore, но он немного более приспособлен к нашим потребностям.
Эта проблема часто появляется, поэтому я рекомендую потратить некоторое время на изучение этой проблемы. См: