1 android illegalstateexception firebase firebase-storage
我想从 android 上的 firebase 文件夹下载所有文件。
这是我的代码
try {
StorageReference reference = storage.getReference().child("Ringtone");
reference.listAll().addOnCompleteListener(new OnCompleteListener<ListResult>() {
@Override
public void onComplete(@NonNull Task<ListResult> task) {
if (task.isComplete()){
task.addOnSuccessListener(new OnSuccessListener<ListResult>() { /////line 82 == 1st line where i am getting error
@Override
public void onSuccess(ListResult listResult) {
for (StorageReference item : listResult.getItems()) {
RingtoneModel ringtoneModel = new RingtoneModel();
ringtoneModel.setUri(item.getDownloadUrl().getResult()); /////line 88 == 2nd line where i am getting error here
item.getMetadata().addOnSuccessListener(new OnSuccessListener<StorageMetadata>() {
@Override
public void onSuccess(StorageMetadata storageMetadata) {
ringtoneModel.setSongName(storageMetadata.getName());
Toast.makeText(MainActivity.this, "ring name saved", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
Log.e("metadata error",e.getMessage());
}
});
}
}
});}else {
Toast.makeText(MainActivity.this, (CharSequence) task.getException(), Toast.LENGTH_SHORT).show();
}
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.e("list all error",e.getMessage());
}
}); }catch (Exception e){
Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
Log.e("all errors",e.getMessage());}
}
Run Code Online (Sandbox Code Playgroud)
Logcat错误消息
/com.example.alarm E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.alarm, PID: 433
java.lang.IllegalStateException: Task is not yet complete
at com.google.android.gms.common.internal.Preconditions.checkState(Unknown Source)
at com.google.android.gms.tasks.zzu.zzb(Unknown Source)
at com.google.android.gms.tasks.zzu.getResult(Unknown Source)
at com.example.alarm.MainActivity$3.onSuccess(MainActivity.java:88)
at com.example.alarm.MainActivity$3.onSuccess(MainActivity.java:82)
Run Code Online (Sandbox Code Playgroud)
我的文件夹和文件在 firebase 数据库中的路径
Firebase storage >Rington<my files
<--我尝试过的 --> 我尝试添加 addonsuuccesslistner 、 addoncompletelitner、task.isComplete()、task.issuccessfull() 以及更多内容
虽然addOnSuccessListener和addOnFailureListener对于处理异步任务的结果很有用,但当您需要像这里一样将事物链接在一起时,它们并不是很有用。
查看您的代码,您调用以下行:
StorageReference item;
item.getDownloadUrl().getResult()
Run Code Online (Sandbox Code Playgroud)
抛出您得到的异常是因为您在调用之前没有等待此任务完成getResult()。
Task<String> downloadUrlTask = item.getDownloadUrl();
downloadUrlTask
.addOnSuccessListener(result -> {
// now do something with result
})
.addOnFailureListener(e -> {
// now do something with the exception
});
Run Code Online (Sandbox Code Playgroud)
虽然如果这就是您所需要的,上面的代码很有帮助,但您要做的是等待它完成,getMetadata()以便您可以创建类的实例RingtoneModel。
这就是Tasks实用程序类的用武之地。
Tasks.whenAll(Collection<Task<?>> tasks)只有当所有任务都tasks成功完成时才会成功。
Task<String> downloadUrlTask = item.getDownloadUrl();
Task<StorageMetadata> metadataTask = item.getMetadata();
return Tasks
.whenAll([ // wait for these tasks to finish successfully
downloadUrlTask,
metadataTask
])
.addOnSuccessListener(() -> { // then assemble its RingtoneModel
RingtoneModel ringtoneModel = new RingtoneModel();
ringtoneModel.setUri(downloadUrlTask.getResult());
ringtoneModel.setSongName(metadataTask.getResult().getName());
// we've now got a RingtoneModel! but what to do with it?
});
Run Code Online (Sandbox Code Playgroud)
而不是addOnSuccessListener()在上面的代码中使用,如果我们使用,onSuccessTask()我们可以返回RingtoneModel后面,这样Task<void>fromTasks.whenAll()现在是一个Task<RingtoneModel>. 为此,我们需要使用Tasks.forResult()which 将我们的RingtoneModel并将其转换为Task<RingtoneModel>.
// function that takes a StorageReference and
// returns a task that resolves to a RingtoneModel
StorageReference item -> {
Task<String> downloadUrlTask = item.getDownloadUrl();
Task<StorageMetadata> metadataTask = item.getMetadata();
return Tasks
.whenAll([ // wait for these tasks to finish successfully
downloadUrlTask,
metadataTask
])
.onSuccessTask(() -> { // then assemble its RingtoneModel
RingtoneModel ringtoneModel = new RingtoneModel();
// because these task have finished by now,
// you can safely use getResult() here
ringtoneModel.setUri(downloadUrlTask.getResult());
ringtoneModel.setSongName(metadataTask.getResult().getName());
return Tasks.forResult(ringtoneModel);
});
}
Run Code Online (Sandbox Code Playgroud)
现在我们已经有了 a RingtoneModelfor one StorageReference,我们想把 a 变成List<StorageReference>a List<RingtoneModel>。我们可以使用以下方法来做到这一点
List<Task<RingtoneModel>> getRingtoneTasks = listResult.getItems()
.stream()
.map(convertToRingtoneModel); // the function above
Run Code Online (Sandbox Code Playgroud)
请注意,这里我们用List<Task<RingtoneModel>>的是Task<List<RingtoneModel>>. 为了扭转这个局面,我们再次使用Tasks.whenAll()、onSuccessTask()、。stream().map()Tasks.forResult()
return Tasks
.whenAll(getRingtoneTasks)
.onSuccessTask(() -> {
return Tasks.forResult(
getRingtoneTasks
.stream()
.map(task -> task.getResult());
);
});
Run Code Online (Sandbox Code Playgroud)
现在,您可能会看到上面的块,并认为这是一个非常简洁的实用方法,您是对的,因为您可以使用它来执行相同的操作:
return Tasks.whenAllSuccess(getRingtoneTasks);
Run Code Online (Sandbox Code Playgroud)
将所有这些混合在一起,得到:
public Task<List<RingtoneModel>> getRingtones() {
StorageReference reference = storage.getReference().child("Ringtone");
return reference.listAll() // find all objects under /Ringtone
.onSuccessTask(listResult -> {
// for each item found, assemble a RingtoneModel
List<Task<RingtoneModel>> getRingtoneTasks = listResult.getItems()
.stream()
.map((item) -> {
// A RingtoneModel needs the download URL and the object's metadata
Task<String> downloadUrlTask = item.getDownloadUrl();
Task<StorageMetadata> metadataTask = item.getMetadata();
return Tasks
.whenAll([ // wait for these tasks to finish successfully
downloadUrlTask,
metadataTask
])
.onSuccessTask(() -> { // then assemble the RingtoneModel and return it
RingtoneModel ringtoneModel = new RingtoneModel();
ringtoneModel.setUri(downloadUrlTask.getResult());
ringtoneModel.setSongName(metadataTask.getResult().getName());
return Tasks.forResult(ringtoneModel);
});
});
return Tasks.whenAllSuccess(getRingtoneTasks);
});
}
Run Code Online (Sandbox Code Playgroud)
然后,当您想要获取云存储中的所有铃声时,您只需要:
getRingtones()
.addOnSuccessListener(ringtoneModelList -> {
Toast.makeText(MainActivity.this, "Found " + ringtoneModelList.size() + " ringtones.", Toast.LENGTH_SHORT).show();
// I recommend storing ringtoneModelList in your database of choice
})
.addOnFailureListener(e -> {
Toast.makeText(MainActivity.this, "Failed to get any ringtones.", Toast.LENGTH_SHORT).show();
Log.e("getRingtones error", e); // <-- log the full error to help with debugging
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5318 次 |
| 最近记录: |