0

I am using Rxjava in conjunction with Retrofit. I want to update status of that image as completed in android database. So the real question is what if second image is uploaded first and after that first is uploaded?. Is onNext() is called sequentially as a images in queue gets executed or the images are uploaded in asynchronous manner. I want to know the required solution for this approach. My code so far is as follows.

tisImageEntities = SelectQuery.getImageByStatus(mContext);

    tisImageCount = 0;
    Observable.fromIterable(tisImageEntities)
            .map(tisImageEntity -> new TisImageUploadEntity(tisImageEntity.projectId,
                    tisImageEntity.imagePath.substring(tisImageEntity.imagePath.lastIndexOf("/") + 1), "fit.jpg",
                    tisImageEntity.detail, tisImageEntity.imageType,
                    getBase64EncodedString(tisImageEntity.imagePath)))
            .filter(tisImageUploadEntity -> null!=tisImageUploadEntity.Content)
            .flatMap(tisImageUploadEntity -> hitachiRetrofitApi.uploadTisImages(tisImageUploadEntity))
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeWith(new DisposableObserver<ResponseBody>() {

                @Override
                public void onNext(ResponseBody responseBody) {
                    try {
                        String response = responseBody.string().toString();
                        UpdateQuery.updateTisImageStatus(mContext,tisImageEntities.get(tisImageCount).projectId); // here is image staatus updated correctly??
                        tisImageCount++;
                        Log.d(TAG, "on next for update entity" + response);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(Throwable e) {
                    e.printStackTrace();
                    cancleProgressDialog();
                }

                @Override
                public void onComplete() {
                    Log.d(TAG, "on complete for update entity");
                    cancleProgressDialog();
                }
            });

So in onNext() the update query right? and is it updating the status sequentially? If not then please correct me

user2582324
  • 1,220
  • 1
  • 9
  • 10

1 Answers1

1

flatMap() does not retain the order, so if you will execute multiple requests results will not be emitted sequentially but by result arrived order.

BTW, you should apply io scheduler to the returned Observable at the flatMap() (hitachiRetrofitApi.uploadTisImages(tisImageUploadEntity)) to get parallelism.

for preserving the order you can use concatMapEager() operator, which will gain you parallelism but will preserve the order of source items.

Additionally, just a suggestion, you have different option, as what you are trying to get here is to collect the request result along with the matching request image entity, you can use flatMap() overload with resultSelector param, with this way, you can send down the stream a pair of the result with the matching image entity, update the db with doOnNext(), and map just the result ResponseBody for the Subscriber to handle it.

 Observable.fromIterable(tisImageEntities)
            .map(tisImageEntity -> new TisImageUploadEntity(tisImageEntity.projectId,
                    tisImageEntity.imagePath.substring(tisImageEntity.imagePath.lastIndexOf("/") + 1), "fit.jpg",
                    tisImageEntity.detail, tisImageEntity.imageType,
                    getBase64EncodedString(tisImageEntity.imagePath)))
            .filter(tisImageUploadEntity -> null != tisImageUploadEntity.Content)
            .flatMap(tisImageUploadEntity -> hitachiRetrofitApi.uploadTisImages(tisImageUploadEntity)
                            .subscribeOn(Schedulers.io()),
                    (tisImageUploadEntity, responseBody) -> Pair::new
            )
            .doOnNext(pair -> UpdateQuery.updateTisImageStatus(mContext, pair.first.projectId))
            .map(pair -> pair.second)
            .subscribeOn(Schedulers.io());
yosriz
  • 10,147
  • 2
  • 24
  • 38
  • Ok so by flatmap() i will not get the result in sequence, to guarantee sequentially output concatMapEager() should be used. But, what is the difference between concatMapEager() and concatMap()? – user2582324 Jun 07 '17 at 06:44
  • concatMap() will operate sequentially, meaning it will not subscribe to next Observable until the previous one done emitting, thus it will not apply parallelism, concatMapEager() take this approach only regarding the emissions but not regarding the subscription so parallelism is achieved. – yosriz Jun 07 '17 at 06:48
  • How can i get the tisImageUploadEntity inside onNext() on which the processing is done, so that i can extract some of it's value to display – user2582324 Jun 07 '17 at 12:02
  • in your code you already gets it, at `tisImageEntities.get(tisImageCount)`, so I guess you're asking about my preposition, in that case you can simply omit the mapping the pair of `ResponseBody` and `TisImageUploadEntity` (`.map(pair -> pair.second`), thus you'll have the pair at the Subscriber onNext – yosriz Jun 08 '17 at 04:13