Переменная хороша в методе onComplete, но вне ее равна нулю - PullRequest
0 голосов
/ 22 мая 2019

Итак, у меня есть метод, который я хочу использовать для получения URL-адреса загрузки для изображения, хранящегося в Firebase Storage, это метод:

private void  getUrlAsync (final StorageReference ref, Uri file){
        UploadTask uploadTask = ref.putFile(file);

        Task<Uri> urlTask = uploadTask.continueWithTask(new Continuation<UploadTask.TaskSnapshot, Task<Uri>>() {
            @Override
            public Task<Uri> then(@NonNull Task<UploadTask.TaskSnapshot> task) throws Exception {
                // Continue with the task to get the download URL
                return ref.getDownloadUrl();
            }
        }).addOnCompleteListener(new OnCompleteListener<Uri>() {
            @Override
            public void onComplete(@NonNull Task<Uri> task) {
                if (task.isSuccessful()) {
                    mDownloadUri = Objects.requireNonNull(task.getResult()).toString();
                    Log.d(TAG, "Get Url " + mDownloadUri);
                } else {
                    // Handle failures
                    // ...
                }
            }
        });
    }

mDownloadUri - глобальная переменная.Хорошо, Log.d в этом методе говорит мне, что mDownloadUri = https://firebasestorage.googleapis.com/v0/b/lapitchat-4c76f.appspot.com/o/profile_images%2FCYUpqZy6AOOhLjvc7PG9JvnoY2p1.jpg?alt=media&token=6bd1b103-209d-4fad-b51e-9907a43f098d, это нормально.Если я вызываю этот метод таким образом, mDownloadUri имеет значение null:

final Uri resultUri = result.getUri();

final String current_user_id = mCurrentUser.getUid();

final StorageReference filepath = mImageStorage.child("profile_images").child(current_user_id + ".jpg");

filepath.putFile(resultUri).addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {
                    @Override
                    public void onComplete(@NonNull Task<UploadTask.TaskSnapshot> task) {

                        if(task.isSuccessful()) {

                        mProgressDialog.dismiss();
                        getUrlAsync(filepath, resultUri);
                        Log.d(TAG, "Put File " + mDownloadUri);
                        }

}

Для контекста результат - это изображение, которое возвращается из другого действия, где я обрезаю изображение.Что я могу сделать?Почему вне метода getUrlAsync mDownloadUri имеет значение null?

1 Ответ

1 голос
/ 22 мая 2019

это ничего не регистрирует:

getUrlAsync(filepath, resultUri);
Log.d(TAG, "Put File " + mDownloadUri);

потому что Log.d() выполняется синхронно (он не будет ждать OnCompleteListener), в то время как getUrlAsync() будет выполняться асинхронно (независимо от остальной части выполнения).

mDownloadUri имеет значение только после того, как OnCompleteListener<Uri> доставил результат ... что это проблема синхронизации, основанная на синхронном и асинхронном выполнении, может быть легко доказана ожиданием:

getUrlAsync(filepath, resultUri);
while(this.mDownloadUri == null) {
    Thread.sleep(100); // this obviously is not the answer.
    Log.d(TAG, "mDownloadUri is NULL; awaiting delivery.");
}
Log.d(TAG, "mDownloadUri is: " + this.mDownloadUri);

довольно правильным было бы добавить еще один метод, который обрабатывает результат задачи; например:

public void OnDownloadUri(Uri uri) {
    ...
}

, а затем перезвоните изнутри OnCompleteListener<Uri> (с 1-2 обратными вызовами это все еще может быть вложенным, но когда оно становится более сложным, подобные методы действительно могут помочь уменьшить ад обратного вызова).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...