Android Studio中前置Firebase循环为何晚于后续语句执行
问题根因
你遇到的执行顺序异常是Firebase Storage API的所有操作都是异步执行导致的:
putFile、getDownloadUrl方法都不会阻塞主线程,调用后立刻返回,主线程会继续往下执行后续代码- 你传入的
OnSuccessListener回调只有等后台线程完成对应的上传/获取地址操作后,才会切回主线程执行 - 所以循环只是把所有上传任务提交出去就立刻结束了,主线程马上执行了后面的
Log.d("list","method called")和addtodatabase调用,等后续上传任务逐个完成后,才会执行回调里的打印和链接收集逻辑,自然就出现了顺序颠倒的情况。
修复方案
可以通过上传成功计数判断所有任务是否完成,再执行后续的数据库写入逻辑,修改后的代码逻辑如下:
private void uploadfirebase() { hashMap.put("Images", "nnn"); hashMap.put("Title", "tit"); String childer = System.currentTimeMillis() + FirebaseAuth.getInstance().getCurrentUser().getUid(); databaseReference.child(FirebaseAuth.getInstance().getCurrentUser().getUid()).setValue(hashMap).addOnSuccessListener(new OnSuccessListener<Void>() { @Override public void onSuccess(Void aVoid) { Toast.makeText(UploadImages.this, "Done", Toast.LENGTH_SHORT).show(); } }); ProgressDialog progressDialog = new ProgressDialog(this); progressDialog.setMessage("Uploading"); progressDialog.show(); // 记录总上传数、成功计数 int totalUpload = imagePath.size(); AtomicInteger successCount = new AtomicInteger(0); // 空列表特殊处理 if (totalUpload == 0) { progressDialog.dismiss(); addtodatabase(addToFirebaseUris); return; } for (int i = 0; i < imagePath.size(); i++) { Uri uri = Uri.fromFile(new File(imagePath.get(i))); String currenttime = System.currentTimeMillis() + FirebaseAuth.getInstance().getCurrentUser().getUid(); storageReference.child(currenttime).putFile(uri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() { @Override public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { taskSnapshot.getStorage().getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() { @Override public void onSuccess(Uri uri) { String url = String.valueOf(uri); addToFirebaseUris.add(url); Log.d("list", "addtoFirebaseList size : " + addToFirebaseUris.size()); // 计数+1,判断是否全部上传完成 int current = successCount.incrementAndGet(); if (current == totalUpload) { progressDialog.dismiss(); Log.d("list", "method called"); Toast.makeText(UploadImages.this, "所有图片上传完成", Toast.LENGTH_SHORT).show(); try { addtodatabase(addToFirebaseUris); } catch (Exception e) { Toast.makeText(UploadImages.this, e.getMessage(), Toast.LENGTH_SHORT).show(); } } } }); } }).addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { progressDialog.dismiss(); Toast.makeText(UploadImages.this, e.getMessage(), Toast.LENGTH_SHORT).show(); } }); } }
修改说明
- 新增
totalUpload记录需要上传的图片总数,新增AtomicInteger类型的successCount记录已成功获取下载链接的数量,保证多回调并发场景下计数正确 - 把原本写在循环外的
addtodatabase调用、完成日志等逻辑,移到每次下载链接获取成功的回调里,判断所有任务都完成后再执行 - 增加空列表判断,避免没有图片需要上传时进度条一直显示的问题
内容的提问来源于stack exchange,提问作者Naman Mandliya
相关产品推荐
相关产品推荐

