Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
510 views
in Technique[技术] by (71.8m points)

rx java - rxJava how to make sequential call while being able to acess previous parameter

This is the flow I need to follow to create a file record in my server

Black arrow is flow
Red arrow is dependency
This is one big function
enter image description here

I need help designing this in rxjava that make them happen sequentially while the later single is able to get the reference

I can create some single for each time taking task

public static Single<byte[]> processData(byte[] fileData))
public static Single<APIResponse> callAPI(String id, byte[] processedData)
public static Single<UploadResponse> uploadData(String url)

This is my attempt
I tried using flatMap's resultSelector as described here
Retrofit and RxJava: How to combine two requests and get access to both results?



    private static Single<FinalResult> bigFunction(String id, int type, String jwt, byte[] fileData){

        return processData(fileData).flatMap(new Function<byte[], SingleSource<APIResponse>>() {
            @Override
            public SingleSource<APIResponse> apply(byte[] processedData) throws Throwable {
                return callAPI(id, processedData);
            }
        }, new BiFunction<byte[], APIResponse, UploadResponse>() {
            @Override
            public FinalResult apply(byte[] processData, APIResponse apiResponse) throws Throwable {
                if (processData.size() > LIMIT){
                    uploadData(apiResponse.getUrl());  // I am stuck here how to return a FinalResult() after this uploadData() is complete
                }else{
                   return new FinalResult(); // if no need to upload, done
                }
                
            }
        });
    }


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If you don't need a result then you can ignoreElement() to convert your flow into Completable and use toSingleDefault(...) function:

uploadData(apiResponse.getUrl())
    .ignoreElement()
    .toSingleDefault(new FinalResult());

In case you just need to convert the response into FinalResult then you can use map(...):

uploadData(apiResponse.getUrl())
     .map(uploadResponse -> new FinalResult(uploadResponse));

In case you have to utilize the result from uploadData(..) with any external calls or whatever then flatMap() is your choice:

uploadData(apiResponse.getUrl())
    .flatMap(uploadResponse -> {
        // do whatever you want with response
        return Single.just(new FinalResult(uploadResponse));
    });

UPDATE:

In your case it can be simplified:

return processData(fileData)
    .flatMap(processedData -> {
        Single<FinalResult> postProcessing;
        if (processedData.length > LIMIT) {
            postProcessing = uploadData(apiResponse.getUrl())
                                .map(response -> new FinalResult(response));
        } else {
            postProcessing = Single.just(new FinalResult());
        }
        return callAPI(id, processedData)
            .ignoreElement()
            .andThen(postProcessing);
            
    });

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...