You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RxJava+Retrofit多图上传:串行执行与批量成功回调需求咨询

RxJava + Retrofit: Multi-Image Upload Solutions

Alright, let's tackle these two image upload scenarios step by step using your existing single-image upload API as the foundation. First, let's recap the API and response model we're working with:

Single-Image Upload API

@Multipart
@POST("addImage")
Observable<ImageUploadResponse> savePhoto(@Part MultipartBody.Part image);

Server Response POJO

Make sure you have this model class set up (using Gson/Moshi for parsing):

public class ImageUploadResponse {
    private boolean isSuccess;
    private boolean isError;
    private String message;
    private PayLoad payLoad;

    // Getters, setters, and inner PayLoad class
    public static class PayLoad {
        private String imagePath;
        // Getters and setters
    }
}

Scenario 1: Parallel Uploads - Trigger onNext Only When All Succeed

Approach

We want to upload all images at the same time, and only emit a result if every upload is successful. Here's how to pull it off:

  1. Convert your list of image parts into an Observable stream.
  2. Use flatMap to kick off each single-image upload in parallel.
  3. Validate each response—if any upload fails, throw an error to stop the sequence.
  4. Use toList() to wait for all successful uploads, then emit the collected results.

Code Implementation

// Assume you've already converted your images to MultipartBody.Part
List<MultipartBody.Part> imageParts = ...;

Observable.fromIterable(imageParts)
    .flatMap(imagePart -> apiService.savePhoto(imagePart)
        // Validate each upload response
        .map(response -> {
            if (!response.isSuccess()) {
                throw new RuntimeException("Upload failed: " + response.getMessage());
            }
            return response.getPayLoad().getImagePath();
        })
        // Optional: Add retry logic for transient failures
        .retry(2))
    // Wait for all uploads to succeed, then collect paths into a list
    .toList()
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(
        successfulImagePaths -> {
            // All images uploaded successfully!
            // Run your onNext logic here with the list of paths
        },
        error -> {
            // At least one upload failed—handle the error here
        }
    );

Key Notes

  • toList() is perfect here: it waits for every upstream emission to complete, then emits a single list. If any upload fails, the sequence jumps straight to onError.
  • We added a map operator to validate each response—this ensures only successful uploads contribute to the final result.
  • subscribeOn(Schedulers.io()) keeps network calls off the UI thread, while observeOn(AndroidSchedulers.mainThread()) brings the result back to your app's UI layer (adjust if you're not building for Android).

Scenario 2: Serial Uploads - Get ArrayList of Results When All Succeed

Approach

For sequential uploads (one after another), we'll swap flatMap with concatMap—this operator processes each upload in order, waiting for the previous one to finish before starting the next. Then we'll collect all successful results into an ArrayList as requested.

Code Implementation

List<MultipartBody.Part> imageParts = ...;

Observable.fromIterable(imageParts)
    // Use concatMap for strict sequential execution
    .concatMap(imagePart -> apiService.savePhoto(imagePart)
        .map(response -> {
            if (!response.isSuccess()) {
                throw new RuntimeException("Upload failed: " + response.getMessage());
            }
            return response.getPayLoad().getImagePath();
        })
        .retry(2))
    // Collect all paths into a list, then convert to ArrayList
    .toList()
    .map(ArrayList::new)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(
        arrayListOfPaths -> {
            // All images uploaded sequentially!
            // Use the ArrayList<String> of successful paths here
        },
        error -> {
            // Any upload failed—handle the error here
        }
    );

Key Notes

  • concatMap guarantees sequential execution: each upload starts only after the previous one completes successfully. If any upload fails, the sequence stops immediately.
  • map(ArrayList::new) converts the default List from toList() into an ArrayList to match your requirement.
  • Just like the parallel scenario, we validate each response to ensure only successful uploads make it to the final list.

内容的提问来源于stack exchange,提问作者Surinder Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:02:21