Bios90
Bios90

Reputation: 811

RxJava chain observable with download

I have an object that can contains urls

class MyObject
(
    var url_image:String? = null,
    var url_document:String? = null,
    var file_image:File? = null,
    var file_document:File? = null
)

Also i have a method to download urls, this method returns Observable<File>

fun download_file(url:String): Observable<File>
{
     //Some logic for creating file, downloading data from url and returning this file as Observable
}

I need to create a method where i would pass myObject, and if needed it will download it urls and finally return Observable<MyObject>. Something like this:

fun prepareForShare(obj: MyObject): Observable<MyObject>
{
    return Observable.just(obj)
            .map(
                {
                    if (obj.url_image != null)
                    {
                        download_file(obj.url_image!!)
                        ...
                        .subscribe(
                        {
                            obj.file_image = it
                        })
                    }

                    if (obj.url_document != null)
                    {
                        download_file(obj.url_image!!)
                        ...
                        .subscribe(
                        {
                            obj.file_document = it
                        })
                    }
                }))
}

How should i make this chain of requests in a right way?

Upvotes: 0

Views: 43

Answers (1)

Christilyn Arjona
Christilyn Arjona

Reputation: 2283

You can combine all requests using the zip(...) operator and transform the MyObject in the flatMap{...} callback:

fun prepareForShare(obj: MyObject): Observable<MyObject> {
    return Observable.zip(
        if (obj.url_image != null) {
            download_file(obj.url_image!!).flatMap { 
                obj.file_image = it
                return@flatMap Observable.just(obj)
            }
        } else Observable.just(obj),
        if (obj.url_document != null) {
            download_file(obj.url_document!!).flatMap { 
                obj.file_document = it
                return@flatMap Observable.just(obj)
            }
        } else Observable.just(obj),
        BiFunction { o1, o2 ->
            obj.file_image = o1.file_image
            obj.file_document = o2.file_document
            obj
        }
    )
}

Alternatively, for a more cleaner approach, you can wrap File in your custom holder object. For example:

data class MyFile(var file: File?)

and emit MyFile(null) if url is empty:

fun download_file(url:String?): Observable<MyFile>
{
    if (url == null) return Observable.just(MyFile(null))
    ...
}

fun prepareForShare(obj: MyObject): Observable<MyObject> {
    return Observable.zip(
        download_file(obj.url_image),
        download_file(obj.url_document),
        BiFunction { file1, file2 ->
            obj.file_image = file1.file
            obj.file_document = file2.file
            obj
        }
    )
}

Upvotes: 1

Related Questions