Mientras repasaba los tutoriales de Firebase Storage y Database para Android, me encontré con un problema para priorizar las consultas.
Necesito guardar los datos de un visitante Firestore Database
y una imagen de un visitante en el Firebase Storage
con un solo clic de botón. Entonces, tengo el siguiente método java en Android:
public void saveNewVisitor() {
Uri file = Uri.fromFile(new File(image_path));
StorageReference imageRef = storageRef.child("images/"+file.getLastPathSegment());
UploadTask uploadTask = imageRef.putFile(file);
uploadTask.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception exception) {
// Handle unsuccessful uploads
}
}).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
downloadURL = taskSnapshot.getDownloadUrl();
}
});
//-----------------------------------
Map<String, Object> dataToSave = new HashMap<String, Object>();
dataToSave.put(NAME, visitorName);
dataToSave.put(AGE, visitorAge);
dataToSave.put(GENDER, visitorGender);
dataToSave.put(IMAGE_URL, String.valueOf(downloadURL));
CollectionReference mColRef = FirebaseFirestore.getInstance().collection("visitors");
mColRef.add(dataToSave).addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
@Override
public void onSuccess(DocumentReference documentReference) {
Log.d(TAG, "Visitor has been saved!");
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.w(TAG, "Error adding a visitor", e);
}
});
}
En el código anterior, ocurren dos acciones. En la primera parte, se guarda una imagen en Firebase Storage y OnSuccessListener
se genera URL
para descargar esa imagen para su uso futuro. En la segunda parte, los datos de texto, incluida la URL generada anteriormente, se guardan en la base de datos.
Entonces, el problema es que Android y Firebase están ejecutando la consulta de datos de texto primero y luego ejecutando la consulta de guardado de imágenes. Esto resulta en la URL = null
base de datos en el momento de guardar los datos downloadURL = null
.
Mi pregunta es cómo priorizar la consulta de guardado de imágenes como ALTA para asegurarme de que se ejecutará antes de la consulta de guardado de datos de texto. Los documentos de Firebase no son tan claros sobre este tema. Se agradece cualquier tipo de ayuda o sugerencia para resolver el problema.
La carga de un archivo a Firebase mediante un UploadTask
se realiza de forma asincrónica y, por lo tanto, su tarea de carga aún se está ejecutando y aún no se ha completado antes de llamar mColRef.add(dataToSave)
, que también se ejecuta de forma asincrónica.
Para encadenar ambos métodos asincrónicos, deberá mover la segunda mitad de la lógica de su método dentro del onSuccess()
bloque de su UploadTask
. De esa manera, la operación de su base de datos solo se realiza una vez que se haya completado la tarea de carga y se le garantiza que tendrá acceso a la URL de descarga.
Para obtener un ejemplo completo, puede dividir el método en dos partes para que sea más fácil ver lo que está sucediendo:
public void saveNewVisitor() {
Uri file = Uri.fromFile(new File(image_path));
StorageReference imageRef = storageRef.child("images/"+file.getLastPathSegment());
UploadTask uploadTask = imageRef.putFile(file);
uploadTask.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception exception) {
// Handle unsuccessful uploads
}
}).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
downloadURL = taskSnapshot.getDownloadUrl();
saveNewVisitorToDatabase(String.valueOf(downloadURL));
}
});
}
private void saveNewVisitorToDatabase(String downloadURL) {
Map<String, Object> dataToSave = new HashMap<String, Object>();
dataToSave.put(NAME, visitorName);
dataToSave.put(AGE, visitorAge);
dataToSave.put(GENDER, visitorGender);
dataToSave.put(IMAGE_URL, downloadURL);
CollectionReference mColRef = FirebaseFirestore.getInstance().collection("visitors");
mColRef.add(dataToSave).addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
@Override
public void onSuccess(DocumentReference documentReference) {
Log.d(TAG, "Visitor has been saved!");
// Once we reach here, we can guarantee that the upload task
// and this database operation were both successful
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.w(TAG, "Error adding a visitor", e);
}
});
}
Este artículo se recopila de Internet, indique la fuente cuando se vuelva a imprimir.
En caso de infracción, por favor [email protected] Eliminar
Déjame decir algunas palabras