【问题标题】:How to make retrofit api request for each item in list with rxjava?如何使用 rxjava 对列表中的每个项目进行改造 api 请求?
【发布时间】:2018-06-20 09:08:44
【问题描述】:

我对 RxJava 很陌生,虽然我看到了多个与我所问的问题相关的问题,但我似乎无法将它们完全拼凑起来。

我有一个包含以下数据的 PostPatrol 对象:

public class PostPatrol {
   String checkpoint_name;
   String status;
   int user;
   String detail;
   List<String> photos;

   public PostPatrol(int cpId, String checkpoint_name, String detail, List<String> photos, String detail) {
       this.cpId = cpId;
       this.checkpoint_name = checkpoint_name;
       this.detail = detail;
       this.photos = photos;
       this.status = status;
   }

   //getters and setters
}

我现在要做的是将本地照片列表保存到这个 PostPatrol 记录中,但在此之前我必须通过改造一张一张地上传照片,取回一个 url 并将其保存到一个列表中然后我将照片设置为 PostPatrol 记录。

一旦我为某个 PostPatrol 记录保存了所有需要的详细信息,然后我会通过改造再次发送该记录。

目前,我是这样做的:

  1. 我将照片传递给一个函数来一张一张地上传图片
  2. 函数是这样的:

    private void uploadImage(List<String> photos, String folder, long requestId) {
        final int size = photos.size();
        final long reqId = requestId;
    
        for (String path : photos) {
            File file = new File(path);
            RequestBody requestBody = RequestBody.create(MediaType.parse("image/*"), file);
            MultipartBody.Part body = MultipartBody.Part.createFormData("image", file.getName(), requestBody);
            RequestBody folderName = RequestBody.create(MediaType.parse("text/plain"), folder);
    
            ApiEndpointInterface apiEndpointInterface = RetrofitManager.getApiInterface();
    
            Call<FileInfo> call4File = apiEndpointInterface.postFile(body, folderName);
    
            call4File.enqueue(new ApiCallback<FileInfo>() {
                @Override
                protected void do4Failure(Throwable t) {
                    Log.d(TAG, t.toString());
                    snackbar = Snackbar.make(viewPendingRequestLayout, R.string.sb_image_upload_error, Snackbar.LENGTH_SHORT);
                    snackbar.show();
                    position++;
                }
    
                @Override
                protected void do4PositiveResponse(Response<FileInfo> response) {
                    Log.d(TAG, "Uploaded Image");
                    FileInfo fileDetails = response.body();
                    listUrls.add(fileDetails.getImage());
                    position++;
                    if (position == size) {
                        postRequest(reqId);
                        position = 0;
                    }
                }
    
                @Override
                protected void do4NegativeResponse(Response<FileInfo> response) {
                    String bodyMsg = "";
                    try {
                        bodyMsg = new String(response.errorBody().bytes());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    Log.d(TAG, bodyMsg);
                    snackbar = Snackbar.make(viewPendingRequestLayout, R.string.sb_image_upload_error, Snackbar.LENGTH_SHORT);
                    snackbar.show();
                    position++;
                }
            });
        }
    }
    

do4PositiveResponse 中,我使用局部变量来跟踪我是否已上传所有照片,然后再将它们发送到将列表保存到 PostPatrol 记录的函数。但有时,我会遇到一些问题,因为它触发得太晚或太早,根本无法上传照片。

  1. 这是我在postRequest()上的代码

    private void postRequest(long requestId) {
        if(mapIdPatrol.containsKey(requestId)){
            PostPatrol postPatrol = mapIdPatrol.get(requestId);
            postPatrol.setPhotos(listUrls);
            postPatrolRequest(postPatrol, requestId);
        }
        listUrls = new ArrayList<>();
    }
    
  2. 最后是我在postPatrolRequest()上的代码

    private void postPatrolRequest(final PostPatrol postPatrol, final long requestId){
        ApiEndpointInterface apiEndpointInterface = RetrofitManager.getApiInterface();
        Call<ResponseId> call4Handle = apiEndpointInterface.handleCheckpoint(postPatrol);
    
        call4Handle.enqueue(new ApiCallback<ResponseId>() {
            @Override
            protected void do4Failure(Throwable t) {
                finishUploading();
                Log.d(TAG, t.toString());
            }
            @Override
            protected void do4PositiveResponse(Response<ResponseId> response) {
                RequestsDataSource.removeRequest(getApplication(),requestId);
                finishUploading();
            }
            @Override
            protected void do4NegativeResponse(Response<ResponseId> response) {
                finishUploading();
                String bodyMsg = "";
                try {
                    bodyMsg = new String(response.errorBody().bytes());
                } catch (IOException e) {
                    e.printStackTrace();
                }
                Log.d(TAG, bodyMsg);
                snackbar = Snackbar.make(viewPendingRequestLayout, getResources().getText(R.string.sb_negative_response), Snackbar.LENGTH_SHORT);
                snackbar.show();
            }
        });
    
    }
    

我知道这是非常低效的,所以我希望得到您的帮助,以便我可以尝试使用 RxJava 找到解决方法。谢谢。

【问题讨论】:

    标签: android retrofit rx-java rx-java2 rx-android


    【解决方案1】:

    操作是原子的吗?即如果通过 Retrofit 保存某些照片失败,您还需要继续吗?

    无论如何,大致的解决方案将是这样的(伪代码):

    Observable<String> urls = Observable.from(listOfPhotoFilePaths)
        .flatMapDelayError(path -> { return retrofit.save(readFile(path))})
        .toList()
    
    Observable<PostPatrol> pp = urls
        .map(list -> { return new PostPatrol(list)})
    

    【讨论】:

      猜你喜欢
      • 2015-06-26
      • 1970-01-01
      • 1970-01-01
      • 2022-01-24
      • 2018-10-21
      • 1970-01-01
      • 2016-07-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多