如何用RxKotlin在Kotlin中同步执行循环完成Firebase上传与Firestore提交
解决方案
核心是用RxKotlin的序列操作符将异步任务转为可控的同步执行流程,确保每个反馈项的所有图片上传完成后再提交Firestore,所有反馈处理完毕后再清理本地数据。
步骤1:封装Firebase Task为Rx Single
给Firebase的Task添加扩展函数,方便转换成Rx的Single类型:
import com.google.android.gms.tasks.Task import io.reactivex.Single import io.reactivex.SingleEmitter fun <T> Task<T>.toSingle(): Single<T> { return Single.create { emitter: SingleEmitter<T> -> this.addOnCompleteListener { task -> if (task.isSuccessful) { emitter.onSuccess(task.result!!) } else { emitter.onError(task.exception ?: Exception("Task failed without exception")) } } } }
步骤2:重构图片上传与数据提交逻辑
修改uploadImageAndToFireBase方法,返回Single<Unit>,用Rx控制图片上传的顺序和URL收集:
private fun uploadImageAndToFireBase( feedbackModel: FeedbackModel, email: String, firstName: String, lastName: String, uuid: String ): Single<Unit> { // 无图片直接提交数据 if (feedbackModel.imageList.isEmpty()) { return Single.fromCallable { uploadDataToFirebaseFeedbackDocument(feedbackModel, emptyList(), email, firstName, lastName, uuid) } } // 遍历图片列表,逐个上传并收集URL return Observable.fromIterable(feedbackModel.imageList.withIndex()) .concatMapSingle { (index, imagePath) -> val ref = storageReference?.child("tests/feedback/images$index.jpg") ?: return@concatMapSingle Single.error<Uri>(Exception("Storage reference is null")) ref.putFile(Uri.parse(imagePath)) .continueWithTask { ref.downloadUrl } .toSingle() } .toList() // 收集所有图片的下载URL .flatMap { listOfImagePath -> Single.fromCallable { uploadDataToFirebaseFeedbackDocument(feedbackModel, listOfImagePath, email, firstName, lastName, uuid) } } }
步骤3:重构批量反馈发送逻辑
修改sendListOfFeedBack方法,用concatMap保证每个反馈项顺序执行,全部完成后再清理本地数据:
private fun sendListOfFeedBack( listOfFeedBack: ArrayList<FeedbackModel>, email: String, firstName: String, lastName: String, uuid: String ): Single<String?> { return if (checkNetworkDataAvailableOrNot()) { Observable.fromIterable(listOfFeedBack) .concatMapSingle { feedbackModel -> uploadImageAndToFireBase(feedbackModel, email, firstName, lastName, uuid) } .ignoreElements() // 忽略元素,只关注完成信号 .andThen( Single.fromCallable { appPreference.clearAllFeedback() REMOTE_SAVED } ) .onErrorReturn { // 处理错误,比如返回本地保存标记或自定义错误信息 LOCAL_SAVED } } else { Single.just(LOCAL_SAVED) } }
关键说明
concatMapSingle:保证Observable序列中的每个任务按顺序执行,前一个任务完成后才会启动下一个,彻底解决原代码异步并行导致的顺序混乱问题。toList():收集所有图片上传后的URL,确保所有图片上传完成后才调用uploadDataToFirebaseFeedbackDocument,避免listOfImagePath为空的情况。- 错误处理:通过
onErrorReturn捕获整个流程中的异常,可根据需求调整错误后的行为(比如回退到本地保存)。
内容的提问来源于stack exchange,提问作者MARSH
相关产品推荐
相关产品推荐

