Search code examples
androidrx-java2rx-android

Update List of objects that is dependent on two other API responses with RxJava


So, basically I have a list of objects that need to be updated. In order to update each object I need to call 2 dependent API calls that will eventually return data (in this case it is a user avatar).

This is what I am trying to do:

private Observable<List<User>> fetchFileInfo(List<User> userList) {
    return Observable.fromIterable(userList)
            .concatMap((Function<User, ObservableSource<FileData>>) user -> fetchFileInfoById(user.getId()))
            .concatMap((Function<FileData, ObservableSource<String>>) fileData -> fetchAvatarUrl(fileData.getEntityId()))
            .concatMap((Function<String, ObservableSource<User>>) avatarUrl -> ???)
            .toList()
            .toObservable();
}

private Observable<FileData> fetchFileInfoById(int id) {
    return getApiService()
            .getFileInfo(id)
            .map(fileDataResponseWrapper -> fileDataResponseWrapper.getData().get(0));
}

private Observable<String> fetchAvatarUrl(int entityId) {
    return getApiService()
            .getFile(entityId)
            .map(responseBodyResponse -> responseBodyResponse.raw().request().url().toString());
}

So, first I fetch the file for each user and then I fetch the avatar for that file info. But, how do I update each of the objects with the avatar that I've received?


Solution

  • Create nested rx chain:

    return Observable.fromIterable(userList)
        .concatMap(user -> {
            return fetchFileInfoById(user.getId())
                .concatMap(fileData -> fetchAvatarUrl(fileData.getEntityId()))
                .concatMap(avatarUrl -> getUpdatedUser(user, avatarUrl))
        })
        .toList()
        .toObservable();
    

    You can reference the user instance in the inner chain.

    Second option is to create wrappers like this example:

    private Observable<List<User>> fetchFileInfo(List<User> userList) {
        return Observable.fromIterable(userList)
                .concatMap((Function<User, ObservableSource<Pair>>) user -> new Pair(user, fetchFileInfoById(user.getId())))
                .concatMap((Function<Pair, ObservableSource<Triple>>) pair -> new Triple(pair.user, pair.fileData, fetchAvatarUrl(pair.fileData.getEntityId())))
                .concatMap((Function<Triple, ObservableSource<User>>) triple -> getUpdatedUser(triple.user, triple.avatarUrl))
                .toList()
                .toObservable();
    }
    
    
    
    class Pair {
        User user;
        FileData fileData;
    }
    
    class Triple {
        User user;
        FileData fileData;
        String avatarUrl;
    }