Search code examples
androiddictionaryobservableflatmapreactivex

Rxjava : Apply treatment on members of an object


I hava a function which is returning an object containing a list from a html page :

@Override
public Observable<MediaList> getMediaListFromUrl(String url) {
    return getHtml(url)
            .map(new Func1<String, MediaList>() {
                @Override
                public MediaList call(String s) {
                    return interpreter.interpretMediaResultsFromHtml(s);
                }
            });
}

What I would like to do next is:

for(Media media : mediaList.getMedias()) {
    if (media.getImageUrl().contains("couvertureAjax")) {
        // fetch media.getImageUrl
        // replace the image url with the result
    }
}

and at the end, return the original MediaList object with the replaced image urls. I think I should use flatmap and from somewhere, but I don't know exactly how.

MediaList.java:

import android.os.Parcel;
import android.os.Parcelable;

import java.util.List;

public class MediaList implements Parcelable {
    public static final String TAG = MediaList.class.getSimpleName();
    private List<Media> medias;
    private String nextPageUrl;

    public MediaList() {}

    protected MediaList(Parcel in) {
        medias = in.createTypedArrayList(Media.CREATOR);
        nextPageUrl = in.readString();
    }

    public List<Media> getMedias() {
        return medias;
    }

    public void setMedias(List<Media> medias) {
        this.medias = medias;
    }

    public String getNextPageUrl() {
        return nextPageUrl;
    }

    public void setNextPageUrl(String nextPageUrl) {
        this.nextPageUrl = nextPageUrl;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeTypedList(medias);
        dest.writeString(nextPageUrl);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    public static final Creator<MediaList> CREATOR = new Creator<MediaList>() {
        @Override
        public MediaList createFromParcel(Parcel in) {
            return new MediaList(in);
        }

        @Override
        public MediaList[] newArray(int size) {
            return new MediaList[size];
        }
    };
}

Solution

  • One way to do this :

    @Override
    public Observable<MediaList> getMediaList(String url) {
        return getHtml(url)
                .flatMap(new Func1<String, Observable<MediaList>>() {
                    @Override
                    public Observable<MediaList> call(String s) {
                        MediaList mediaList = interpreter.interpretMediaResultsFromHtml(s);
                        Observable<List<Media>> list = Observable.from(mediaList.getMedias())
                                .flatMap(new Func1<Media, Observable<Media>>() {
                                    @Override
                                    public Observable<Media> call(Media media) {
                                        if (media.needImagePreload()) {
                                            return getMediaLoadedImage(media.getImageUrl(), media);
                                        } else {
                                            return Observable.just(media);
                                        }
                                    }
                                })
                                .toList();
                        return Observable.zip(Observable.just(mediaList.getNextPageUrl()), list, new Func2<String, List<Media>, MediaList>() {
                            @Override
                            public MediaList call(String s, List<Media> medias) {
                                return zipMediaList(s, medias);
                            }
                        });
                    }
                });
    }
    
    
    private MediaList zipMediaList(String s, List<Media> medias) {
        MediaList mediaList = DefaultFactory.MediaList.constructDefaultInstance();
        mediaList.setNextPageUrl(s);
        mediaList.setMedias(medias);
        return mediaList;
    }
    

    I think they are easier ways to do this, but it works.