for循环内addOnSuccessListener无法关闭ProgressDialog 多图上传如何关闭进度框
解决方案
核心逻辑:Firebase的文件上传、下载链接获取都是异步执行的,你不能直接在for循环结束的位置关闭弹窗——此时所有上传任务还在后台执行,没有完成。你需要统计所有任务的完成状态,等到全部文件上传成功、且所有下载链接都获取存储完成后再关闭进度弹窗。
具体修改如下:
- 新增线程安全的计数器,统计已完成的有效任务数(必须是拿到下载链接并存储完成才算1个完成任务)
- 每次成功存储下载链接后对计数器+1,当计数器数值等于总上传任务数时,关闭弹窗、执行后续的Firebase Database写入操作
- 原有失败逻辑保留,只要有一个任务失败就直接关闭弹窗提示错误
修改后的完整代码:
// 先给你的类新增一个成员变量,存储进度弹窗引用,方便后续访问 private ProgressDialog mDialog; private void uploadScreenshot() { // 多图上传建议修改判断条件,原来的screenshotUri大概率是单图上传的遗留判断 if (ScreenshotList != null && !ScreenshotList.isEmpty()) { mDialog = new ProgressDialog(this); mDialog.setMessage("Uploading..."); mDialog.setCancelable(false); // 建议加上,避免用户手动取消导致任务状态混乱 mDialog.show(); // 总上传任务数 final int totalUploadTasks = ScreenshotList.size(); // 线程安全的计数器,避免多线程场景下计数错误 final AtomicInteger completedTaskCount = new AtomicInteger(0); String ssName = UUID.randomUUID().toString(); final StorageReference screenshotFolder = storageReference.child("screenshots/" + ssName); for (int upload_count = 0; upload_count < ScreenshotList.size(); upload_count++) { Uri IndividualImage = Uri.parse(ScreenshotList.get(upload_count)); final StorageReference ScreenshotName = screenshotFolder.child(IndividualImage.getLastPathSegment()); ScreenshotName.putFile(IndividualImage) .addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() { @Override public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { ScreenshotName.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() { @Override public void onSuccess(Uri uri) { String url = String.valueOf(uri); storeLink(url, completedTaskCount, totalUploadTasks); } }); } }) .addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { if (mDialog != null && mDialog.isShowing()) { mDialog.dismiss(); } Toast.makeText(AppList.this, "" + e.getMessage(), Toast.LENGTH_SHORT).show(); } }) .addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() { @Override public void onProgress(UploadTask.TaskSnapshot taskSnapshot) { double progress = (100.0 * taskSnapshot.getBytesTransferred() / taskSnapshot.getTotalByteCount()); mDialog.setMessage("Uploaded " + (int)progress + "%"); } }); } } } private void storeLink(String url, AtomicInteger completedTaskCount, int totalTasks) { ssList.add(url); newApp.setScreenshot(ssList); // 计数器自增,判断是否所有任务都完成 int currentCompleted = completedTaskCount.incrementAndGet(); if (currentCompleted == totalTasks) { // 所有任务完成,关闭弹窗 if (mDialog != null && mDialog.isShowing()) { mDialog.dismiss(); } // 这里执行你要的newApp写入Firebase Database的操作 Toast.makeText(AppList.this, "Screenshots Uploaded !!!", Toast.LENGTH_SHORT).show(); } }
补充说明:如果你的minSDK版本较高,也可以用Tasks.whenAllSuccess()批量监听所有任务的完成状态,逻辑会更简洁,上面的方案是兼容所有版本的通用写法。
内容的提问来源于stack exchange,提问作者Amit Swami
相关产品推荐
相关产品推荐

