2017-10-22 3 views
0

안드로이드 용 파이어베이스 스토리지 및 데이터베이스 자습서를 진행하면서 질문의 우선 순위를 정하기 위해 문제가 발생했습니다.안드로이드에서 파이어베이스 쿼리의 우선 순위 지정 방법

버튼을 한 번 클릭하여 방문자 데이터를 Firestore Database에 저장하고 방문자 이미지를 Firebase Storage으로 저장해야합니다. 그래서, 안드로이드에 다음 자바 메서드가 있습니다 :

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); 
     } 
    }); 
} 

위의 코드에서 두 가지 작업이 발생합니다. 첫 번째 부분에서는 이미지가 Firebase Storage에 저장되고 OnSuccessListener에서 나중에 사용할 수 있도록 해당 이미지를 다운로드하려면 URL이 생성됩니다. 두 번째 부분에서는 위에서 생성 된 URL을 포함하여 텍스트 데이터가 데이터베이스에 저장됩니다.

그래서 문제는 안드로이드와 파이어베이스가 텍스트 데이터 쿼리를 먼저 실행 한 다음 이미지 저장 쿼리를 실행하는 것입니다. 데이터 downloadURL = null 저장시와 마찬가지로 데이터베이스에 URL = null이 표시됩니다.

제 질문은 이미지 저장 쿼리가 텍스트 데이터 저장 쿼리 전에 실행되는지 확인하기 위해 이미지 저장 쿼리의 우선 순위를 높이는 방법입니다. Firebase 문서는이 주제에 대해 명확하지 않습니다. 문제를 해결하기위한 도움이나 제안이 있으면 감사하겠습니다.

+0

예를 참조 https://github.com/firebase/quickstart-android/tree/master을 : 그것은 무슨 일이 일어나고 쉽게 확인할 수 있도록 완전한 예를 들어

, 당신은 두 부분으로 방법을 나눌 수/storage myuploadservice.java –

답변

0

UploadTask을 사용하여 Firebase에 파일을 업로드하면 asynchronously이 수행되므로 업로드 작업이 아직 실행 중이며 을 호출하기 전에 아직 완료되지 않았습니다.이 작업도 비동기 적으로 실행됩니다.

두 비동기 메서드를 연결하려면 UploadTask 블록의 블록 내부에서 메서드 논리의 두 번째 절반을 이동해야합니다. 그렇게하면 데이터베이스 작업은 업로드 작업이 완료되고 다운로드 URL에 대한 액세스 권한이 보장 된 후에 만 ​​수행됩니다.

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); 
     } 
    }); 
} 
+0

잘 작동하지만 주어진 이미지에 이미지를 사용할 수 없다면 어떻게 될까요? 이미지를 저장할 필요는 없지만 텍스트 데이터를 저장해야합니다. 이 시나리오에서는'onSuccess'가 결코 트리거되지 않으며'saveNewVisitorToDatabase' 메소드도 트리거되지 않습니다. 감사. – Dan

+0

전체 공개 : - 단일 텍스트 데이터 당 여러 개의 이미지가 있으며 텍스트 데이터 당 이미지 수 (있을 경우)를 보장 할 수는 없습니다. 현재는'if-statements'를 많이 사용하고 있으며 코드의 가독성과 실행으로보기에는 좋지 않습니다. – Dan

+0

이것은 두 가지 메소드를 분리하는 또 다른 이유입니다. 저장할 이미지가 없을 때'saveNewVisitorToDatabase()'를 대신 호출 할 수 있습니다. – Grimthorr