1
votes

I am new to Rx and I've been wondering how to properly emit values one by one (lazy load images in this example). What is the best way to do this without encountering concurrency issues?

This is my code:

@Override
public Observable<Bitmap> getPhotos(final String placeId) {
    return Observable.create(new ObservableOnSubscribe<Bitmap>() {
        @Override
        public void subscribe(ObservableEmitter<Bitmap> emitter) throws Exception {
            try {
                PlacePhotoMetadataResult res = Places.GeoDataApi
                        .getPlacePhotos(googleApiClient, placeId)
                        .await();
                PlacePhotoMetadataBuffer buffer = res.getPhotoMetadata();

                for (PlacePhotoMetadata photoMetadata : buffer) {
                    Bitmap photo = photoMetadata
                            .getPhoto(googleApiClient)
                            .await()
                            .getBitmap();

                    emitter.onNext(photo);
                }

                buffer.release();
            } catch (Exception ex) {
                emitter.onError(ex);
            } finally {
                emitter.onComplete();
            }
        }
    });
}

Thanks!

1
where is the loop here? - yosriz

1 Answers

1
votes

You really should invest some time in bridging PendingResult<T> to Observable<T> (or Single, or Flowable(my preference)). Then all your code can be expressed as:

private static <T> Observable<T> toObservable(PendingResult<T> result) {
    // 
}

public Observable<Bitmap> getPhotos(final String placeId) {
    return Observable
            .just(placeId)
            .flatMap(id -> toObservable(Places.GeoDataApi.getPlacePhotos(googleApiClient, placeId)))
            .flatMapIterable(PlacePhotoMetadataResult::getPhotoMetadata)
            .flatMap(metadata -> toObservable(metadata.getPhoto(googleApiClient)))
            .map(Photo::getBitmap);
}

A good place to start looking into how to do the bridge is this library, but it's RxJava 1 only.